a693f2490af1de654d1712fc055ee9332813c628
[ira/wip.git] / source4 / torture / nbt / winsreplication.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    WINS replication testing
5
6    Copyright (C) Andrew Tridgell        2005
7    Copyright (C) Stefan Metzmacher      2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "includes.h"
24 #include "libcli/wrepl/winsrepl.h"
25 #include "lib/events/events.h"
26 #include "lib/socket/socket.h"
27 #include "system/network.h"
28 #include "lib/socket/netif.h"
29 #include "librpc/gen_ndr/ndr_nbt.h"
30 #include "torture/torture.h"
31 #include "torture/nbt/proto.h"
32 #include "param/param.h"
33
34 #define CHECK_STATUS(tctx, status, correct) \
35         torture_assert_ntstatus_equal(tctx, status, correct, \
36                                                                   "Incorrect status")
37
38 #define CHECK_VALUE(tctx, v, correct) \
39         torture_assert(tctx, (v) == (correct), \
40                                    talloc_asprintf(tctx, "Incorrect value %s=%d - should be %d\n", \
41                        #v, v, correct))
42
43 #define CHECK_VALUE_UINT64(tctx, v, correct) \
44         torture_assert(tctx, (v) == (correct), \
45                 talloc_asprintf(tctx, "Incorrect value %s=%llu - should be %llu\n", \
46                        #v, (long long)v, (long long)correct))
47
48 #define CHECK_VALUE_STRING(tctx, v, correct) \
49         torture_assert_str_equal(tctx, v, correct, "Invalid value")
50
51 #define _NBT_NAME(n,t,s) {\
52         .name   = n,\
53         .type   = t,\
54         .scope  = s\
55 }
56
57 static const char *wrepl_name_type_string(enum wrepl_name_type type)
58 {
59         switch (type) {
60         case WREPL_TYPE_UNIQUE: return "UNIQUE";
61         case WREPL_TYPE_GROUP: return "GROUP";
62         case WREPL_TYPE_SGROUP: return "SGROUP";
63         case WREPL_TYPE_MHOMED: return "MHOMED";
64         }
65         return "UNKNOWN_TYPE";
66 }
67
68 static const char *wrepl_name_state_string(enum wrepl_name_state state)
69 {
70         switch (state) {
71         case WREPL_STATE_ACTIVE: return "ACTIVE";
72         case WREPL_STATE_RELEASED: return "RELEASED";
73         case WREPL_STATE_TOMBSTONE: return "TOMBSTONE";
74         case WREPL_STATE_RESERVED: return "RESERVED";
75         }
76         return "UNKNOWN_STATE";
77 }
78
79 /*
80   test how assoc_ctx's are only usable on the connection
81   they are created on.
82 */
83 static bool test_assoc_ctx1(struct torture_context *tctx)
84 {
85         bool ret = true;
86         struct wrepl_request *req;
87         struct wrepl_socket *wrepl_socket1;
88         struct wrepl_associate associate1;
89         struct wrepl_socket *wrepl_socket2;
90         struct wrepl_associate associate2;
91         struct wrepl_pull_table pull_table;
92         struct wrepl_packet packet;
93         struct wrepl_send_ctrl ctrl;
94         struct wrepl_packet *rep_packet;
95         struct wrepl_associate_stop assoc_stop;
96         NTSTATUS status;
97         struct nbt_name name;
98         const char *address;
99
100         if (!torture_nbt_get_name(tctx, &name, &address))
101                 return false;
102
103         torture_comment(tctx, "Test if assoc_ctx is only valid on the conection it was created on\n");
104
105         wrepl_socket1 = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
106         wrepl_socket2 = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
107
108         torture_comment(tctx, "Setup 2 wrepl connections\n");
109         status = wrepl_connect(wrepl_socket1, wrepl_best_ip(tctx->lp_ctx, address), address);
110         CHECK_STATUS(tctx, status, NT_STATUS_OK);
111
112         status = wrepl_connect(wrepl_socket2, wrepl_best_ip(tctx->lp_ctx, address), address);
113         CHECK_STATUS(tctx, status, NT_STATUS_OK);
114
115         torture_comment(tctx, "Send a start association request (conn1)\n");
116         status = wrepl_associate(wrepl_socket1, &associate1);
117         CHECK_STATUS(tctx, status, NT_STATUS_OK);
118
119         torture_comment(tctx, "association context (conn1): 0x%x\n", associate1.out.assoc_ctx);
120
121         torture_comment(tctx, "Send a start association request (conn2)\n");
122         status = wrepl_associate(wrepl_socket2, &associate2);
123         CHECK_STATUS(tctx, status, NT_STATUS_OK);
124
125         torture_comment(tctx, "association context (conn2): 0x%x\n", associate2.out.assoc_ctx);
126
127         torture_comment(tctx, "Send a replication table query, with assoc 1 (conn2), the anwser should be on conn1\n");
128         ZERO_STRUCT(packet);
129         packet.opcode                      = WREPL_OPCODE_BITS;
130         packet.assoc_ctx                   = associate1.out.assoc_ctx;
131         packet.mess_type                   = WREPL_REPLICATION;
132         packet.message.replication.command = WREPL_REPL_TABLE_QUERY;
133         ZERO_STRUCT(ctrl);
134         ctrl.send_only = true;
135         req = wrepl_request_send(wrepl_socket2, &packet, &ctrl);
136         status = wrepl_request_recv(req, tctx, &rep_packet);
137         CHECK_STATUS(tctx, status, NT_STATUS_OK);
138
139         torture_comment(tctx, "Send a association request (conn2), to make sure the last request was ignored\n");
140         status = wrepl_associate(wrepl_socket2, &associate2);
141         CHECK_STATUS(tctx, status, NT_STATUS_OK);
142
143         torture_comment(tctx, "Send a replication table query, with invalid assoc (conn1), receive answer from conn2\n");
144         pull_table.in.assoc_ctx = 0;
145         req = wrepl_pull_table_send(wrepl_socket1, &pull_table);
146         status = wrepl_request_recv(req, tctx, &rep_packet);
147         CHECK_STATUS(tctx, status, NT_STATUS_OK);
148
149         torture_comment(tctx, "Send a association request (conn1), to make sure the last request was handled correct\n");
150         status = wrepl_associate(wrepl_socket1, &associate2);
151         CHECK_STATUS(tctx, status, NT_STATUS_OK);
152
153         assoc_stop.in.assoc_ctx = associate1.out.assoc_ctx;
154         assoc_stop.in.reason    = 4;
155         torture_comment(tctx, "Send a association stop request (conn1), reson: %u\n", assoc_stop.in.reason);
156         status = wrepl_associate_stop(wrepl_socket1, &assoc_stop);
157         CHECK_STATUS(tctx, status, NT_STATUS_END_OF_FILE);
158
159         assoc_stop.in.assoc_ctx = associate2.out.assoc_ctx;
160         assoc_stop.in.reason    = 0;
161         torture_comment(tctx, "Send a association stop request (conn2), reson: %u\n", assoc_stop.in.reason);
162         status = wrepl_associate_stop(wrepl_socket2, &assoc_stop);
163         CHECK_STATUS(tctx, status, NT_STATUS_OK);
164
165         torture_comment(tctx, "Close 2 wrepl connections\n");
166         talloc_free(wrepl_socket1);
167         talloc_free(wrepl_socket2);
168         return ret;
169 }
170
171 /*
172   test if we always get back the same assoc_ctx
173 */
174 static bool test_assoc_ctx2(struct torture_context *tctx)
175 {
176         struct wrepl_socket *wrepl_socket;
177         struct wrepl_associate associate;
178         uint32_t assoc_ctx1;
179         struct nbt_name name;
180         NTSTATUS status;
181         const char *address;
182
183         if (!torture_nbt_get_name(tctx, &name, &address))
184                 return false;
185
186         torture_comment(tctx, "Test if we always get back the same assoc_ctx\n");
187
188         wrepl_socket = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
189         
190         torture_comment(tctx, "Setup wrepl connections\n");
191         status = wrepl_connect(wrepl_socket, wrepl_best_ip(tctx->lp_ctx, address), address);
192         CHECK_STATUS(tctx, status, NT_STATUS_OK);
193
194         torture_comment(tctx, "Send 1st start association request\n");
195         status = wrepl_associate(wrepl_socket, &associate);
196         CHECK_STATUS(tctx, status, NT_STATUS_OK);
197         assoc_ctx1 = associate.out.assoc_ctx;
198         torture_comment(tctx, "1st association context: 0x%x\n", associate.out.assoc_ctx);
199
200         torture_comment(tctx, "Send 2nd start association request\n");
201         status = wrepl_associate(wrepl_socket, &associate);
202         torture_assert_ntstatus_ok(tctx, status, "2nd start association failed");
203         torture_assert(tctx, associate.out.assoc_ctx == assoc_ctx1, 
204                                    "Different context returned");
205         torture_comment(tctx, "2nd association context: 0x%x\n", associate.out.assoc_ctx);
206
207         torture_comment(tctx, "Send 3rd start association request\n");
208         status = wrepl_associate(wrepl_socket, &associate);
209         torture_assert(tctx, associate.out.assoc_ctx == assoc_ctx1, 
210                                    "Different context returned");
211         CHECK_STATUS(tctx, status, NT_STATUS_OK);
212         torture_comment(tctx, "3rd association context: 0x%x\n", associate.out.assoc_ctx);
213
214         torture_comment(tctx, "Close wrepl connections\n");
215         talloc_free(wrepl_socket);
216         return true;
217 }
218
219
220 /*
221   display a replication entry
222 */
223 static void display_entry(struct torture_context *tctx, struct wrepl_name *name)
224 {
225         int i;
226
227         torture_comment(tctx, "%s\n", nbt_name_string(tctx, &name->name));
228         torture_comment(tctx, "\tTYPE:%u STATE:%u NODE:%u STATIC:%u VERSION_ID: %llu\n",
229                 name->type, name->state, name->node, name->is_static, (long long)name->version_id);
230         torture_comment(tctx, "\tRAW_FLAGS: 0x%08X OWNER: %-15s\n",
231                 name->raw_flags, name->owner);
232         for (i=0;i<name->num_addresses;i++) {
233                 torture_comment(tctx, "\tADDR: %-15s OWNER: %-15s\n", 
234                         name->addresses[i].address, name->addresses[i].owner);
235         }
236 }
237
238 /*
239   test a full replication dump from a WINS server
240 */
241 static bool test_wins_replication(struct torture_context *tctx)
242 {
243         struct wrepl_socket *wrepl_socket;
244         NTSTATUS status;
245         int i, j;
246         struct wrepl_associate associate;
247         struct wrepl_pull_table pull_table;
248         struct wrepl_pull_names pull_names;
249         struct nbt_name name;
250         const char *address;
251
252         if (!torture_nbt_get_name(tctx, &name, &address))
253                 return false;
254
255         torture_comment(tctx, "Test one pull replication cycle\n");
256
257         wrepl_socket = wrepl_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
258         
259         torture_comment(tctx, "Setup wrepl connections\n");
260         status = wrepl_connect(wrepl_socket, wrepl_best_ip(tctx->lp_ctx, address), address);
261         CHECK_STATUS(tctx, status, NT_STATUS_OK);
262
263         torture_comment(tctx, "Send a start association request\n");
264
265         status = wrepl_associate(wrepl_socket, &associate);
266         CHECK_STATUS(tctx, status, NT_STATUS_OK);
267
268         torture_comment(tctx, "association context: 0x%x\n", associate.out.assoc_ctx);
269
270         torture_comment(tctx, "Send a replication table query\n");
271         pull_table.in.assoc_ctx = associate.out.assoc_ctx;
272
273         status = wrepl_pull_table(wrepl_socket, tctx, &pull_table);
274         if (NT_STATUS_EQUAL(NT_STATUS_NETWORK_ACCESS_DENIED,status)) {
275                 struct wrepl_packet packet;
276                 struct wrepl_request *req;
277
278                 ZERO_STRUCT(packet);
279                 packet.opcode                      = WREPL_OPCODE_BITS;
280                 packet.assoc_ctx                   = associate.out.assoc_ctx;
281                 packet.mess_type                   = WREPL_STOP_ASSOCIATION;
282                 packet.message.stop.reason         = 0;
283
284                 req = wrepl_request_send(wrepl_socket, &packet, NULL);
285                 talloc_free(req);
286
287                 torture_fail(tctx, "We are not a valid pull partner for the server");
288         }
289         CHECK_STATUS(tctx, status, NT_STATUS_OK);
290
291         torture_comment(tctx, "Found %d replication partners\n", pull_table.out.num_partners);
292
293         for (i=0;i<pull_table.out.num_partners;i++) {
294                 struct wrepl_wins_owner *partner = &pull_table.out.partners[i];
295                 torture_comment(tctx, "%s   max_version=%6llu   min_version=%6llu type=%d\n",
296                        partner->address, 
297                        (long long)partner->max_version, 
298                        (long long)partner->min_version, 
299                        partner->type);
300
301                 pull_names.in.assoc_ctx = associate.out.assoc_ctx;
302                 pull_names.in.partner = *partner;
303                 
304                 status = wrepl_pull_names(wrepl_socket, tctx, &pull_names);
305                 CHECK_STATUS(tctx, status, NT_STATUS_OK);
306
307                 torture_comment(tctx, "Received %d names\n", pull_names.out.num_names);
308
309                 for (j=0;j<pull_names.out.num_names;j++) {
310                         display_entry(tctx, &pull_names.out.names[j]);
311                 }
312         }
313
314         torture_comment(tctx, "Close wrepl connections\n");
315         talloc_free(wrepl_socket);
316         return true;
317 }
318
319 struct test_wrepl_conflict_conn {
320         const char *address;
321         struct wrepl_socket *pull;
322         uint32_t pull_assoc;
323
324 #define TEST_OWNER_A_ADDRESS "127.65.65.1"
325 #define TEST_ADDRESS_A_PREFIX "127.0.65"
326 #define TEST_OWNER_B_ADDRESS "127.66.66.1"
327 #define TEST_ADDRESS_B_PREFIX "127.0.66"
328 #define TEST_OWNER_X_ADDRESS "127.88.88.1"
329 #define TEST_ADDRESS_X_PREFIX "127.0.88"
330
331         struct wrepl_wins_owner a, b, c, x;
332
333         struct socket_address *myaddr;
334         struct socket_address *myaddr2;
335         struct nbt_name_socket *nbtsock;
336         struct nbt_name_socket *nbtsock2;
337
338         struct nbt_name_socket *nbtsock_srv;
339         struct nbt_name_socket *nbtsock_srv2;
340
341         uint32_t addresses_best_num;
342         struct wrepl_ip *addresses_best;
343
344         uint32_t addresses_best2_num;
345         struct wrepl_ip *addresses_best2;
346
347         uint32_t addresses_all_num;
348         struct wrepl_ip *addresses_all;
349
350         uint32_t addresses_mhomed_num;
351         struct wrepl_ip *addresses_mhomed;
352 };
353
354 static const struct wrepl_ip addresses_A_1[] = {
355         {
356         .owner  = TEST_OWNER_A_ADDRESS,
357         .ip     = TEST_ADDRESS_A_PREFIX".1"
358         }
359 };
360 static const struct wrepl_ip addresses_A_2[] = {
361         {
362         .owner  = TEST_OWNER_A_ADDRESS,
363         .ip     = TEST_ADDRESS_A_PREFIX".2"
364         }
365 };
366 static const struct wrepl_ip addresses_A_3_4[] = {
367         {
368         .owner  = TEST_OWNER_A_ADDRESS,
369         .ip     = TEST_ADDRESS_A_PREFIX".3"
370         },
371         {
372         .owner  = TEST_OWNER_A_ADDRESS,
373         .ip     = TEST_ADDRESS_A_PREFIX".4"
374         }
375 };
376 static const struct wrepl_ip addresses_A_3_4_X_3_4[] = {
377         {
378         .owner  = TEST_OWNER_A_ADDRESS,
379         .ip     = TEST_ADDRESS_A_PREFIX".3"
380         },
381         {
382         .owner  = TEST_OWNER_A_ADDRESS,
383         .ip     = TEST_ADDRESS_A_PREFIX".4"
384         },
385         {
386         .owner  = TEST_OWNER_X_ADDRESS,
387         .ip     = TEST_ADDRESS_X_PREFIX".3"
388         },
389         {
390         .owner  = TEST_OWNER_X_ADDRESS,
391         .ip     = TEST_ADDRESS_X_PREFIX".4"
392         }
393 };
394 static const struct wrepl_ip addresses_A_3_4_B_3_4[] = {
395         {
396         .owner  = TEST_OWNER_A_ADDRESS,
397         .ip     = TEST_ADDRESS_A_PREFIX".3"
398         },
399         {
400         .owner  = TEST_OWNER_A_ADDRESS,
401         .ip     = TEST_ADDRESS_A_PREFIX".4"
402         },
403         {
404         .owner  = TEST_OWNER_B_ADDRESS,
405         .ip     = TEST_ADDRESS_B_PREFIX".3"
406         },
407         {
408         .owner  = TEST_OWNER_B_ADDRESS,
409         .ip     = TEST_ADDRESS_B_PREFIX".4"
410         }
411 };
412 static const struct wrepl_ip addresses_A_3_4_OWNER_B[] = {
413         {
414         .owner  = TEST_OWNER_B_ADDRESS,
415         .ip     = TEST_ADDRESS_A_PREFIX".3"
416         },
417         {
418         .owner  = TEST_OWNER_B_ADDRESS,
419         .ip     = TEST_ADDRESS_A_PREFIX".4"
420         }
421 };
422 static const struct wrepl_ip addresses_A_3_4_X_3_4_OWNER_B[] = {
423         {
424         .owner  = TEST_OWNER_B_ADDRESS,
425         .ip     = TEST_ADDRESS_A_PREFIX".3"
426         },
427         {
428         .owner  = TEST_OWNER_B_ADDRESS,
429         .ip     = TEST_ADDRESS_A_PREFIX".4"
430         },
431         {
432         .owner  = TEST_OWNER_B_ADDRESS,
433         .ip     = TEST_ADDRESS_X_PREFIX".3"
434         },
435         {
436         .owner  = TEST_OWNER_B_ADDRESS,
437         .ip     = TEST_ADDRESS_X_PREFIX".4"
438         }
439 };
440
441 static const struct wrepl_ip addresses_A_3_4_X_1_2[] = {
442         {
443         .owner  = TEST_OWNER_A_ADDRESS,
444         .ip     = TEST_ADDRESS_A_PREFIX".3"
445         },
446         {
447         .owner  = TEST_OWNER_A_ADDRESS,
448         .ip     = TEST_ADDRESS_A_PREFIX".4"
449         },
450         {
451         .owner  = TEST_OWNER_X_ADDRESS,
452         .ip     = TEST_ADDRESS_X_PREFIX".1"
453         },
454         {
455         .owner  = TEST_OWNER_X_ADDRESS,
456         .ip     = TEST_ADDRESS_X_PREFIX".2"
457         }
458 };
459
460 static const struct wrepl_ip addresses_B_1[] = {
461         {
462         .owner  = TEST_OWNER_B_ADDRESS,
463         .ip     = TEST_ADDRESS_B_PREFIX".1"
464         }
465 };
466 static const struct wrepl_ip addresses_B_2[] = {
467         {
468         .owner  = TEST_OWNER_B_ADDRESS,
469         .ip     = TEST_ADDRESS_B_PREFIX".2"
470         }
471 };
472 static const struct wrepl_ip addresses_B_3_4[] = {
473         {
474         .owner  = TEST_OWNER_B_ADDRESS,
475         .ip     = TEST_ADDRESS_B_PREFIX".3"
476         },
477         {
478         .owner  = TEST_OWNER_B_ADDRESS,
479         .ip     = TEST_ADDRESS_B_PREFIX".4"
480         }
481 };
482 static const struct wrepl_ip addresses_B_3_4_X_3_4[] = {
483         {
484         .owner  = TEST_OWNER_B_ADDRESS,
485         .ip     = TEST_ADDRESS_B_PREFIX".3"
486         },
487         {
488         .owner  = TEST_OWNER_B_ADDRESS,
489         .ip     = TEST_ADDRESS_B_PREFIX".4"
490         },
491         {
492         .owner  = TEST_OWNER_X_ADDRESS,
493         .ip     = TEST_ADDRESS_X_PREFIX".3"
494         },
495         {
496         .owner  = TEST_OWNER_X_ADDRESS,
497         .ip     = TEST_ADDRESS_X_PREFIX".4"
498         }
499 };
500 static const struct wrepl_ip addresses_B_3_4_X_1_2[] = {
501         {
502         .owner  = TEST_OWNER_B_ADDRESS,
503         .ip     = TEST_ADDRESS_B_PREFIX".3"
504         },
505         {
506         .owner  = TEST_OWNER_B_ADDRESS,
507         .ip     = TEST_ADDRESS_B_PREFIX".4"
508         },
509         {
510         .owner  = TEST_OWNER_X_ADDRESS,
511         .ip     = TEST_ADDRESS_X_PREFIX".1"
512         },
513         {
514         .owner  = TEST_OWNER_X_ADDRESS,
515         .ip     = TEST_ADDRESS_X_PREFIX".2"
516         }
517 };
518
519 static const struct wrepl_ip addresses_X_1_2[] = {
520         {
521         .owner  = TEST_OWNER_X_ADDRESS,
522         .ip     = TEST_ADDRESS_X_PREFIX".1"
523         },
524         {
525         .owner  = TEST_OWNER_X_ADDRESS,
526         .ip     = TEST_ADDRESS_X_PREFIX".2"
527         }
528 };
529 static const struct wrepl_ip addresses_X_3_4[] = {
530         {
531         .owner  = TEST_OWNER_X_ADDRESS,
532         .ip     = TEST_ADDRESS_X_PREFIX".3"
533         },
534         {
535         .owner  = TEST_OWNER_X_ADDRESS,
536         .ip     = TEST_ADDRESS_X_PREFIX".4"
537         }
538 };
539
540 static struct test_wrepl_conflict_conn *test_create_conflict_ctx(
541                 struct torture_context *tctx, const char *address)
542 {
543         struct test_wrepl_conflict_conn *ctx;
544         struct wrepl_associate associate;
545         struct wrepl_pull_table pull_table;
546         struct socket_address *nbt_srv_addr;
547         NTSTATUS status;
548         uint32_t i;
549         struct interface *ifaces;
550
551         ctx = talloc_zero(tctx, struct test_wrepl_conflict_conn);
552         if (!ctx) return NULL;
553
554         ctx->address    = address;
555         ctx->pull       = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
556         if (!ctx->pull) return NULL;
557
558         torture_comment(tctx, "Setup wrepl conflict pull connection\n");
559         status = wrepl_connect(ctx->pull, wrepl_best_ip(tctx->lp_ctx, ctx->address), ctx->address);
560         if (!NT_STATUS_IS_OK(status)) return NULL;
561
562         status = wrepl_associate(ctx->pull, &associate);
563         if (!NT_STATUS_IS_OK(status)) return NULL;
564
565         ctx->pull_assoc = associate.out.assoc_ctx;
566
567         ctx->a.address          = TEST_OWNER_A_ADDRESS;
568         ctx->a.max_version      = 0;
569         ctx->a.min_version      = 0;
570         ctx->a.type             = 1;
571
572         ctx->b.address          = TEST_OWNER_B_ADDRESS;
573         ctx->b.max_version      = 0;
574         ctx->b.min_version      = 0;
575         ctx->b.type             = 1;
576
577         ctx->x.address          = TEST_OWNER_X_ADDRESS;
578         ctx->x.max_version      = 0;
579         ctx->x.min_version      = 0;
580         ctx->x.type             = 1;
581
582         ctx->c.address          = address;
583         ctx->c.max_version      = 0;
584         ctx->c.min_version      = 0;
585         ctx->c.type             = 1;
586
587         pull_table.in.assoc_ctx = ctx->pull_assoc;
588         status = wrepl_pull_table(ctx->pull, ctx->pull, &pull_table);
589         if (!NT_STATUS_IS_OK(status)) return NULL;
590
591         for (i=0; i < pull_table.out.num_partners; i++) {
592                 if (strcmp(TEST_OWNER_A_ADDRESS,pull_table.out.partners[i].address)==0) {
593                         ctx->a.max_version      = pull_table.out.partners[i].max_version;
594                         ctx->a.min_version      = pull_table.out.partners[i].min_version;
595                 }
596                 if (strcmp(TEST_OWNER_B_ADDRESS,pull_table.out.partners[i].address)==0) {
597                         ctx->b.max_version      = pull_table.out.partners[i].max_version;
598                         ctx->b.min_version      = pull_table.out.partners[i].min_version;
599                 }
600                 if (strcmp(TEST_OWNER_X_ADDRESS,pull_table.out.partners[i].address)==0) {
601                         ctx->x.max_version      = pull_table.out.partners[i].max_version;
602                         ctx->x.min_version      = pull_table.out.partners[i].min_version;
603                 }
604                 if (strcmp(address,pull_table.out.partners[i].address)==0) {
605                         ctx->c.max_version      = pull_table.out.partners[i].max_version;
606                         ctx->c.min_version      = pull_table.out.partners[i].min_version;
607                 }
608         }
609
610         talloc_free(pull_table.out.partners);
611
612         ctx->nbtsock = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
613         if (!ctx->nbtsock) return NULL;
614
615         load_interfaces(tctx, lp_interfaces(tctx->lp_ctx), &ifaces);
616
617         ctx->myaddr = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_best_ip(ifaces, address), 0);
618         if (!ctx->myaddr) return NULL;
619
620         for (i = 0; i < iface_count(ifaces); i++) {
621                 if (strcmp(ctx->myaddr->addr, iface_n_ip(ifaces, i)) == 0) continue;
622                 ctx->myaddr2 = socket_address_from_strings(tctx, ctx->nbtsock->sock->backend_name, iface_n_ip(ifaces, i), 0);
623                 if (!ctx->myaddr2) return NULL;
624                 break;
625         }
626
627         status = socket_listen(ctx->nbtsock->sock, ctx->myaddr, 0, 0);
628         if (!NT_STATUS_IS_OK(status)) return NULL;
629
630         ctx->nbtsock_srv = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
631         if (!ctx->nbtsock_srv) return NULL;
632
633         /* Make a port 137 version of ctx->myaddr */
634         nbt_srv_addr = socket_address_from_strings(tctx, ctx->nbtsock_srv->sock->backend_name, ctx->myaddr->addr, lp_nbt_port(tctx->lp_ctx));
635         if (!nbt_srv_addr) return NULL;
636
637         /* And if possible, bind to it.  This won't work unless we are root or in sockewrapper */
638         status = socket_listen(ctx->nbtsock_srv->sock, nbt_srv_addr, 0, 0);
639         talloc_free(nbt_srv_addr);
640         if (!NT_STATUS_IS_OK(status)) {
641                 /* this isn't fatal */
642                 talloc_free(ctx->nbtsock_srv);
643                 ctx->nbtsock_srv = NULL;
644         }
645
646         if (ctx->myaddr2 && ctx->nbtsock_srv) {
647                 ctx->nbtsock2 = nbt_name_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
648                 if (!ctx->nbtsock2) return NULL;
649
650                 status = socket_listen(ctx->nbtsock2->sock, ctx->myaddr2, 0, 0);
651                 if (!NT_STATUS_IS_OK(status)) return NULL;
652
653                 ctx->nbtsock_srv2 = nbt_name_socket_init(ctx, ctx->nbtsock_srv->event_ctx, lp_iconv_convenience(tctx->lp_ctx));
654                 if (!ctx->nbtsock_srv2) return NULL;
655
656                 /* Make a port 137 version of ctx->myaddr2 */
657                 nbt_srv_addr = socket_address_from_strings(tctx, 
658                                                            ctx->nbtsock_srv->sock->backend_name, 
659                                                            ctx->myaddr2->addr, 
660                                                            lp_nbt_port(tctx->lp_ctx));
661                 if (!nbt_srv_addr) return NULL;
662
663                 /* And if possible, bind to it.  This won't work unless we are root or in sockewrapper */
664                 status = socket_listen(ctx->nbtsock_srv2->sock, ctx->myaddr2, 0, 0);
665                 talloc_free(nbt_srv_addr);
666                 if (!NT_STATUS_IS_OK(status)) {
667                         /* this isn't fatal */
668                         talloc_free(ctx->nbtsock_srv2);
669                         ctx->nbtsock_srv2 = NULL;
670                 }
671         }
672
673         ctx->addresses_best_num = 1;
674         ctx->addresses_best = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best_num);
675         if (!ctx->addresses_best) return NULL;
676         ctx->addresses_best[0].owner    = ctx->b.address;
677         ctx->addresses_best[0].ip       = ctx->myaddr->addr;
678
679         ctx->addresses_all_num = iface_count(ifaces);
680         ctx->addresses_all = talloc_array(ctx, struct wrepl_ip, ctx->addresses_all_num);
681         if (!ctx->addresses_all) return NULL;
682         for (i=0; i < ctx->addresses_all_num; i++) {
683                 ctx->addresses_all[i].owner     = ctx->b.address;
684                 ctx->addresses_all[i].ip        = talloc_strdup(ctx->addresses_all, iface_n_ip(ifaces, i));
685                 if (!ctx->addresses_all[i].ip) return NULL;
686         }
687
688         if (ctx->nbtsock_srv2) {
689                 ctx->addresses_best2_num = 1;
690                 ctx->addresses_best2 = talloc_array(ctx, struct wrepl_ip, ctx->addresses_best2_num);
691                 if (!ctx->addresses_best2) return NULL;
692                 ctx->addresses_best2[0].owner   = ctx->b.address;
693                 ctx->addresses_best2[0].ip      = ctx->myaddr2->addr;
694
695                 ctx->addresses_mhomed_num = 2;
696                 ctx->addresses_mhomed = talloc_array(ctx, struct wrepl_ip, ctx->addresses_mhomed_num);
697                 if (!ctx->addresses_mhomed) return NULL;
698                 ctx->addresses_mhomed[0].owner  = ctx->b.address;
699                 ctx->addresses_mhomed[0].ip     = ctx->myaddr->addr;
700                 ctx->addresses_mhomed[1].owner  = ctx->b.address;
701                 ctx->addresses_mhomed[1].ip     = ctx->myaddr2->addr;
702         }
703
704         return ctx;
705 }
706
707 static bool test_wrepl_update_one(struct torture_context *tctx, 
708                                                                   struct test_wrepl_conflict_conn *ctx,
709                                   const struct wrepl_wins_owner *owner,
710                                   const struct wrepl_wins_name *name)
711 {
712         struct wrepl_socket *wrepl_socket;
713         struct wrepl_associate associate;
714         struct wrepl_packet update_packet, repl_send;
715         struct wrepl_table *update;
716         struct wrepl_wins_owner wrepl_wins_owners[1];
717         struct wrepl_packet *repl_recv;
718         struct wrepl_wins_owner *send_request;
719         struct wrepl_send_reply *send_reply;
720         struct wrepl_wins_name wrepl_wins_names[1];
721         uint32_t assoc_ctx;
722         NTSTATUS status;
723
724         wrepl_socket = wrepl_socket_init(ctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
725
726         status = wrepl_connect(wrepl_socket, wrepl_best_ip(tctx->lp_ctx, ctx->address), ctx->address);
727         CHECK_STATUS(tctx, status, NT_STATUS_OK);
728
729         status = wrepl_associate(wrepl_socket, &associate);
730         CHECK_STATUS(tctx, status, NT_STATUS_OK);
731         assoc_ctx = associate.out.assoc_ctx;
732
733         /* now send a WREPL_REPL_UPDATE message */
734         ZERO_STRUCT(update_packet);
735         update_packet.opcode                    = WREPL_OPCODE_BITS;
736         update_packet.assoc_ctx                 = assoc_ctx;
737         update_packet.mess_type                 = WREPL_REPLICATION;
738         update_packet.message.replication.command       = WREPL_REPL_UPDATE;
739         update  = &update_packet.message.replication.info.table;
740
741         update->partner_count   = ARRAY_SIZE(wrepl_wins_owners);
742         update->partners        = wrepl_wins_owners;
743         update->initiator       = "0.0.0.0";
744
745         wrepl_wins_owners[0]    = *owner;
746
747         status = wrepl_request(wrepl_socket, wrepl_socket,
748                                &update_packet, &repl_recv);
749         CHECK_STATUS(tctx, status, NT_STATUS_OK);
750         CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_REPLICATION);
751         CHECK_VALUE(tctx, repl_recv->message.replication.command, WREPL_REPL_SEND_REQUEST);
752         send_request = &repl_recv->message.replication.info.owner;
753
754         ZERO_STRUCT(repl_send);
755         repl_send.opcode                        = WREPL_OPCODE_BITS;
756         repl_send.assoc_ctx                     = assoc_ctx;
757         repl_send.mess_type                     = WREPL_REPLICATION;
758         repl_send.message.replication.command   = WREPL_REPL_SEND_REPLY;
759         send_reply = &repl_send.message.replication.info.reply;
760
761         send_reply->num_names   = ARRAY_SIZE(wrepl_wins_names);
762         send_reply->names       = wrepl_wins_names;
763
764         wrepl_wins_names[0]     = *name;
765
766         status = wrepl_request(wrepl_socket, wrepl_socket,
767                                &repl_send, &repl_recv);
768         CHECK_STATUS(tctx, status, NT_STATUS_OK);
769         CHECK_VALUE(tctx, repl_recv->mess_type, WREPL_STOP_ASSOCIATION);
770         CHECK_VALUE(tctx, repl_recv->message.stop.reason, 0);
771
772         talloc_free(wrepl_socket);
773         return true;
774 }
775
776 static bool test_wrepl_is_applied(struct torture_context *tctx, 
777                                                                   struct test_wrepl_conflict_conn *ctx,
778                                   const struct wrepl_wins_owner *owner,
779                                   const struct wrepl_wins_name *name,
780                                   bool expected)
781 {
782         NTSTATUS status;
783         struct wrepl_pull_names pull_names;
784         struct wrepl_name *names;
785
786         pull_names.in.assoc_ctx = ctx->pull_assoc;
787         pull_names.in.partner   = *owner;
788         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
789                 
790         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
791         CHECK_STATUS(tctx, status, NT_STATUS_OK);
792         torture_assert(tctx, pull_names.out.num_names == (expected?1:0), 
793                        talloc_asprintf(tctx, "Invalid number of records returned - expected %d got %d", expected, pull_names.out.num_names));
794
795         names = pull_names.out.names;
796
797         if (expected) {
798                 uint32_t flags = WREPL_NAME_FLAGS(names[0].type,
799                                                   names[0].state,
800                                                   names[0].node,
801                                                   names[0].is_static);
802                 CHECK_VALUE(tctx, names[0].name.type, name->name->type);
803                 CHECK_VALUE_STRING(tctx, names[0].name.name, name->name->name);
804                 CHECK_VALUE_STRING(tctx, names[0].name.scope, name->name->scope);
805                 CHECK_VALUE(tctx, flags, name->flags);
806                 CHECK_VALUE_UINT64(tctx, names[0].version_id, name->id);
807
808                 if (flags & 2) {
809                         CHECK_VALUE(tctx, names[0].num_addresses,
810                                     name->addresses.addresses.num_ips);
811                 } else {
812                         CHECK_VALUE(tctx, names[0].num_addresses, 1);
813                         CHECK_VALUE_STRING(tctx, names[0].addresses[0].address,
814                                            name->addresses.ip);
815                 }
816         }
817         talloc_free(pull_names.out.names);
818         return true;
819 }
820
821 static bool test_wrepl_mhomed_merged(struct torture_context *tctx, 
822                                                                          struct test_wrepl_conflict_conn *ctx,
823                                      const struct wrepl_wins_owner *owner1,
824                                      uint32_t num_ips1, const struct wrepl_ip *ips1,
825                                      const struct wrepl_wins_owner *owner2,
826                                      uint32_t num_ips2, const struct wrepl_ip *ips2,
827                                      const struct wrepl_wins_name *name2)
828 {
829         NTSTATUS status;
830         struct wrepl_pull_names pull_names;
831         struct wrepl_name *names;
832         uint32_t flags;
833         uint32_t i, j;
834         uint32_t num_ips = num_ips1 + num_ips2;
835
836         for (i = 0; i < num_ips2; i++) {
837                 for (j = 0; j < num_ips1; j++) {
838                         if (strcmp(ips2[i].ip,ips1[j].ip) == 0) {
839                                 num_ips--;
840                                 break;
841                         }
842                 } 
843         }
844
845         pull_names.in.assoc_ctx = ctx->pull_assoc;
846         pull_names.in.partner   = *owner2;
847         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
848
849         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
850         CHECK_STATUS(tctx, status, NT_STATUS_OK);
851         CHECK_VALUE(tctx, pull_names.out.num_names, 1);
852
853         names = pull_names.out.names;
854
855         flags = WREPL_NAME_FLAGS(names[0].type,
856                                  names[0].state,
857                                  names[0].node,
858                                  names[0].is_static);
859         CHECK_VALUE(tctx, names[0].name.type, name2->name->type);
860         CHECK_VALUE_STRING(tctx, names[0].name.name, name2->name->name);
861         CHECK_VALUE_STRING(tctx, names[0].name.scope, name2->name->scope);
862         CHECK_VALUE(tctx, flags, name2->flags | WREPL_TYPE_MHOMED);
863         CHECK_VALUE_UINT64(tctx, names[0].version_id, name2->id);
864
865         CHECK_VALUE(tctx, names[0].num_addresses, num_ips);
866
867         for (i = 0; i < names[0].num_addresses; i++) {
868                 const char *addr = names[0].addresses[i].address; 
869                 const char *owner = names[0].addresses[i].owner;
870                 bool found = false;
871
872                 for (j = 0; j < num_ips2; j++) {
873                         if (strcmp(addr, ips2[j].ip) == 0) {
874                                 found = true;
875                                 CHECK_VALUE_STRING(tctx, owner, owner2->address);
876                                 break;
877                         }
878                 }
879
880                 if (found) continue;
881
882                 for (j = 0; j < num_ips1; j++) {
883                         if (strcmp(addr, ips1[j].ip) == 0) {
884                                 found = true;
885                                 CHECK_VALUE_STRING(tctx, owner, owner1->address);
886                                 break;
887                         }
888                 }
889
890                 if (found) continue;
891
892                 CHECK_VALUE_STRING(tctx, addr, "not found in address list");
893         }
894         talloc_free(pull_names.out.names);
895         return true;
896 }
897
898 static bool test_wrepl_sgroup_merged(struct torture_context *tctx, 
899                                                                          struct test_wrepl_conflict_conn *ctx,
900                                      struct wrepl_wins_owner *merge_owner,
901                                      struct wrepl_wins_owner *owner1,
902                                      uint32_t num_ips1, const struct wrepl_ip *ips1,
903                                      struct wrepl_wins_owner *owner2,
904                                      uint32_t num_ips2, const struct wrepl_ip *ips2,
905                                      const struct wrepl_wins_name *name2)
906 {
907         NTSTATUS status;
908         struct wrepl_pull_names pull_names;
909         struct wrepl_name *names;
910         struct wrepl_name *name = NULL;
911         uint32_t flags;
912         uint32_t i, j;
913         uint32_t num_ips = num_ips1 + num_ips2;
914
915         if (!merge_owner) {
916                 merge_owner = &ctx->c;
917         }
918
919         for (i = 0; i < num_ips1; i++) {
920                 if (owner1 != &ctx->c && strcmp(ips1[i].owner,owner2->address) == 0) {
921                         num_ips--;
922                         continue;
923                 }
924                 for (j = 0; j < num_ips2; j++) {
925                         if (strcmp(ips1[i].ip,ips2[j].ip) == 0) {
926                                 num_ips--;
927                                 break;
928                         }
929                 }
930         }
931
932
933         pull_names.in.assoc_ctx = ctx->pull_assoc;
934         pull_names.in.partner   = *merge_owner;
935         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
936         pull_names.in.partner.max_version = 0;
937
938         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
939         CHECK_STATUS(tctx, status, NT_STATUS_OK);
940
941         names = pull_names.out.names;
942         
943         for (i = 0; i < pull_names.out.num_names; i++) {
944                 if (names[i].name.type != name2->name->type)    continue;
945                 if (!names[i].name.name) continue;
946                 if (strcmp(names[i].name.name, name2->name->name) != 0) continue;
947                 if (names[i].name.scope) continue;
948
949                 name = &names[i];
950         }
951
952         if (pull_names.out.num_names > 0) {
953                 merge_owner->max_version        = names[pull_names.out.num_names-1].version_id;
954         }
955
956         if (!name) {
957                 torture_comment(tctx, "%s: Name '%s' not found\n", __location__, nbt_name_string(ctx, name2->name));
958                 return false;
959         }
960
961         flags = WREPL_NAME_FLAGS(name->type,
962                                  name->state,
963                                  name->node,
964                                  name->is_static);
965         CHECK_VALUE(tctx, name->name.type, name2->name->type);
966         CHECK_VALUE_STRING(tctx, name->name.name, name2->name->name);
967         CHECK_VALUE_STRING(tctx, name->name.scope, name2->name->scope);
968         CHECK_VALUE(tctx, flags, name2->flags);
969
970         CHECK_VALUE(tctx, name->num_addresses, num_ips);
971
972         for (i = 0; i < name->num_addresses; i++) {
973                 const char *addr = name->addresses[i].address; 
974                 const char *owner = name->addresses[i].owner;
975                 bool found = false;
976
977                 for (j = 0; j < num_ips2; j++) {
978                         if (strcmp(addr, ips2[j].ip) == 0) {
979                                 found = true;
980                                 CHECK_VALUE_STRING(tctx, owner, ips2[j].owner);
981                                 break;
982                         }
983                 }
984
985                 if (found) continue;
986
987                 for (j = 0; j < num_ips1; j++) {
988                         if (strcmp(addr, ips1[j].ip) == 0) {
989                                 found = true;
990                                 if (owner1 == &ctx->c) {
991                                         CHECK_VALUE_STRING(tctx, owner, owner1->address);
992                                 } else {
993                                         CHECK_VALUE_STRING(tctx, owner, ips1[j].owner);
994                                 }
995                                 break;
996                         }
997                 }
998
999                 if (found) continue;
1000
1001                 CHECK_VALUE_STRING(tctx, addr, "not found in address list");
1002         }
1003         talloc_free(pull_names.out.names);
1004         return true;
1005 }
1006
1007 static bool test_conflict_same_owner(struct torture_context *tctx, 
1008                                                                          struct test_wrepl_conflict_conn *ctx)
1009 {
1010         static bool ret = true;
1011         struct wrepl_wins_name wins_name1;
1012         struct wrepl_wins_name wins_name2;
1013         struct wrepl_wins_name *wins_name_tmp;
1014         struct wrepl_wins_name *wins_name_last;
1015         struct wrepl_wins_name *wins_name_cur;
1016         uint32_t i,j;
1017         struct nbt_name names[] = {
1018                 _NBT_NAME("_SAME_OWNER_A", 0x00, NULL),
1019                 _NBT_NAME("_SAME_OWNER_A", 0x1C, NULL),
1020         };
1021         struct {
1022                 enum wrepl_name_type type;
1023                 enum wrepl_name_state state;
1024                 enum wrepl_name_node node;
1025                 bool is_static;
1026                 uint32_t num_ips;
1027                 const struct wrepl_ip *ips;
1028         } records[] = {
1029                 {
1030                 .type           = WREPL_TYPE_GROUP,
1031                 .state          = WREPL_STATE_ACTIVE,
1032                 .node           = WREPL_NODE_B,
1033                 .is_static      = false,
1034                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1035                 .ips            = addresses_A_1,
1036                 },{
1037                 .type           = WREPL_TYPE_UNIQUE,
1038                 .state          = WREPL_STATE_ACTIVE,
1039                 .node           = WREPL_NODE_B,
1040                 .is_static      = false,
1041                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1042                 .ips            = addresses_A_1,
1043                 },{
1044                 .type           = WREPL_TYPE_UNIQUE,
1045                 .state          = WREPL_STATE_ACTIVE,
1046                 .node           = WREPL_NODE_B,
1047                 .is_static      = false,
1048                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1049                 .ips            = addresses_A_2,
1050                 },{
1051                 .type           = WREPL_TYPE_UNIQUE,
1052                 .state          = WREPL_STATE_ACTIVE,
1053                 .node           = WREPL_NODE_B,
1054                 .is_static      = true,
1055                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1056                 .ips            = addresses_A_1,
1057                 },{
1058                 .type           = WREPL_TYPE_UNIQUE,
1059                 .state          = WREPL_STATE_ACTIVE,
1060                 .node           = WREPL_NODE_B,
1061                 .is_static      = false,
1062                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1063                 .ips            = addresses_A_2,
1064                 },{
1065                 .type           = WREPL_TYPE_SGROUP,
1066                 .state          = WREPL_STATE_TOMBSTONE,
1067                 .node           = WREPL_NODE_B,
1068                 .is_static      = false,
1069                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1070                 .ips            = addresses_A_2,
1071                 },{
1072                 .type           = WREPL_TYPE_MHOMED,
1073                 .state          = WREPL_STATE_TOMBSTONE,
1074                 .node           = WREPL_NODE_B,
1075                 .is_static      = false,
1076                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1077                 .ips            = addresses_A_1,
1078                 },{
1079                 .type           = WREPL_TYPE_MHOMED,
1080                 .state          = WREPL_STATE_RELEASED,
1081                 .node           = WREPL_NODE_B,
1082                 .is_static      = false,
1083                 .num_ips        = ARRAY_SIZE(addresses_A_2),
1084                 .ips            = addresses_A_2,
1085                 },{
1086                 .type           = WREPL_TYPE_SGROUP,
1087                 .state          = WREPL_STATE_ACTIVE,
1088                 .node           = WREPL_NODE_B,
1089                 .is_static      = false,
1090                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1091                 .ips            = addresses_A_1,
1092                 },{
1093                 .type           = WREPL_TYPE_SGROUP,
1094                 .state          = WREPL_STATE_ACTIVE,
1095                 .node           = WREPL_NODE_B,
1096                 .is_static      = false,
1097                 .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1098                 .ips            = addresses_A_3_4,
1099                 },{
1100                 .type           = WREPL_TYPE_SGROUP,
1101                 .state          = WREPL_STATE_TOMBSTONE,
1102                 .node           = WREPL_NODE_B,
1103                 .is_static      = false,
1104                 .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1105                 .ips            = addresses_B_3_4,
1106                 },{
1107                 /* the last one should always be a unique,tomstone record! */
1108                 .type           = WREPL_TYPE_UNIQUE,
1109                 .state          = WREPL_STATE_TOMBSTONE,
1110                 .node           = WREPL_NODE_B,
1111                 .is_static      = false,
1112                 .num_ips        = ARRAY_SIZE(addresses_A_1),
1113                 .ips            = addresses_A_1,
1114                 }
1115         };
1116
1117         wins_name_tmp   = NULL;
1118         wins_name_last  = &wins_name2;
1119         wins_name_cur   = &wins_name1;
1120
1121         for (j=0; ret && j < ARRAY_SIZE(names); j++) {
1122                 torture_comment(tctx, "Test Replica Conflicts with same owner[%s] for %s\n",
1123                         nbt_name_string(ctx, &names[j]), ctx->a.address);
1124
1125                 for(i=0; ret && i < ARRAY_SIZE(records); i++) {
1126                         wins_name_tmp   = wins_name_last;
1127                         wins_name_last  = wins_name_cur;
1128                         wins_name_cur   = wins_name_tmp;
1129
1130                         if (i > 0) {
1131                                 torture_comment(tctx, "%s,%s%s vs. %s,%s%s with %s ip(s) => %s\n",
1132                                         wrepl_name_type_string(records[i-1].type),
1133                                         wrepl_name_state_string(records[i-1].state),
1134                                         (records[i-1].is_static?",static":""),
1135                                         wrepl_name_type_string(records[i].type),
1136                                         wrepl_name_state_string(records[i].state),
1137                                         (records[i].is_static?",static":""),
1138                                         (records[i-1].ips==records[i].ips?"same":"different"),
1139                                         "REPLACE");
1140                         }
1141
1142                         wins_name_cur->name     = &names[j];
1143                         wins_name_cur->flags    = WREPL_NAME_FLAGS(records[i].type,
1144                                                                    records[i].state,
1145                                                                    records[i].node,
1146                                                                    records[i].is_static);
1147                         wins_name_cur->id       = ++ctx->a.max_version;
1148                         if (wins_name_cur->flags & 2) {
1149                                 wins_name_cur->addresses.addresses.num_ips = records[i].num_ips;
1150                                 wins_name_cur->addresses.addresses.ips     = discard_const_p(struct wrepl_ip,
1151                                                                              records[i].ips);
1152                         } else {
1153                                 wins_name_cur->addresses.ip = records[i].ips[0].ip;
1154                         }
1155                         wins_name_cur->unknown  = "255.255.255.255";
1156
1157                         ret &= test_wrepl_update_one(tctx, ctx, &ctx->a,wins_name_cur);
1158                         if (records[i].state == WREPL_STATE_RELEASED) {
1159                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_last, false);
1160                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_cur, false);
1161                         } else {
1162                                 ret &= test_wrepl_is_applied(tctx, ctx, &ctx->a, wins_name_cur, true);
1163                         }
1164
1165                         /* the first one is a cleanup run */
1166                         if (!ret && i == 0) ret = true;
1167
1168                         if (!ret) {
1169                                 torture_comment(tctx, "conflict handled wrong or record[%u]: %s\n", i, __location__);
1170                                 return ret;
1171                         }
1172                 }
1173         }
1174         return ret;
1175 }
1176
1177 static bool test_conflict_different_owner(struct torture_context *tctx, 
1178                                                                                   struct test_wrepl_conflict_conn *ctx)
1179 {
1180         bool ret = true;
1181         struct wrepl_wins_name wins_name1;
1182         struct wrepl_wins_name wins_name2;
1183         struct wrepl_wins_name *wins_name_r1;
1184         struct wrepl_wins_name *wins_name_r2;
1185         uint32_t i;
1186         struct {
1187                 const char *line; /* just better debugging */
1188                 struct nbt_name name;
1189                 const char *comment;
1190                 bool extra; /* not the worst case, this is an extra test */
1191                 bool cleanup;
1192                 struct {
1193                         struct wrepl_wins_owner *owner;
1194                         enum wrepl_name_type type;
1195                         enum wrepl_name_state state;
1196                         enum wrepl_name_node node;
1197                         bool is_static;
1198                         uint32_t num_ips;
1199                         const struct wrepl_ip *ips;
1200                         bool apply_expected;
1201                         bool sgroup_merge;
1202                         struct wrepl_wins_owner *merge_owner;
1203                         bool sgroup_cleanup;
1204                 } r1, r2;
1205         } records[] = {
1206         /* 
1207          * NOTE: the first record and the last applied one
1208          *       needs to be from the same owner,
1209          *       to not conflict in the next smbtorture run!!!
1210          */
1211         {
1212                 .line   = __location__,
1213                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1214                 .cleanup= true,
1215                 .r1     = {
1216                         .owner          = &ctx->b,
1217                         .type           = WREPL_TYPE_UNIQUE,
1218                         .state          = WREPL_STATE_TOMBSTONE,
1219                         .node           = WREPL_NODE_B,
1220                         .is_static      = false,
1221                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1222                         .ips            = addresses_B_1,
1223                         .apply_expected = true /* ignored */
1224                 },
1225                 .r2     = {
1226                         .owner          = &ctx->a,
1227                         .type           = WREPL_TYPE_UNIQUE,
1228                         .state          = WREPL_STATE_TOMBSTONE,
1229                         .node           = WREPL_NODE_B,
1230                         .is_static      = false,
1231                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1232                         .ips            = addresses_A_1,
1233                         .apply_expected = true /* ignored */
1234                 }
1235         },
1236
1237 /*
1238  * unique vs unique section
1239  */
1240         /* 
1241          * unique,active vs. unique,active
1242          * => should be replaced
1243          */
1244         {
1245                 .line   = __location__,
1246                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1247                 .r1     = {
1248                         .owner          = &ctx->a,
1249                         .type           = WREPL_TYPE_UNIQUE,
1250                         .state          = WREPL_STATE_ACTIVE,
1251                         .node           = WREPL_NODE_B,
1252                         .is_static      = false,
1253                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1254                         .ips            = addresses_A_1,
1255                         .apply_expected = true
1256                 },
1257                 .r2     = {
1258                         .owner          = &ctx->b,
1259                         .type           = WREPL_TYPE_UNIQUE,
1260                         .state          = WREPL_STATE_ACTIVE,
1261                         .node           = WREPL_NODE_B,
1262                         .is_static      = false,
1263                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1264                         .ips            = addresses_B_1,
1265                         .apply_expected = true
1266                 }
1267         },
1268
1269         /* 
1270          * unique,active vs. unique,tombstone
1271          * => should NOT be replaced
1272          */
1273         {
1274                 .line   = __location__,
1275                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1276                 .r1     = {
1277                         .owner          = &ctx->b,
1278                         .type           = WREPL_TYPE_UNIQUE,
1279                         .state          = WREPL_STATE_ACTIVE,
1280                         .node           = WREPL_NODE_B,
1281                         .is_static      = false,
1282                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1283                         .ips            = addresses_B_1,
1284                         .apply_expected = true
1285                 },
1286                 .r2     = {
1287                         .owner          = &ctx->a,
1288                         .type           = WREPL_TYPE_UNIQUE,
1289                         .state          = WREPL_STATE_TOMBSTONE,
1290                         .node           = WREPL_NODE_B,
1291                         .is_static      = false,
1292                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1293                         .ips            = addresses_B_1,
1294                         .apply_expected = false
1295                 }
1296         },
1297
1298         /* 
1299          * unique,released vs. unique,active
1300          * => should be replaced
1301          */
1302         {
1303                 .line   = __location__,
1304                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1305                 .r1     = {
1306                         .owner          = &ctx->b,
1307                         .type           = WREPL_TYPE_UNIQUE,
1308                         .state          = WREPL_STATE_RELEASED,
1309                         .node           = WREPL_NODE_B,
1310                         .is_static      = false,
1311                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1312                         .ips            = addresses_B_1,
1313                         .apply_expected = false
1314                 },
1315                 .r2     = {
1316                         .owner          = &ctx->a,
1317                         .type           = WREPL_TYPE_UNIQUE,
1318                         .state          = WREPL_STATE_ACTIVE,
1319                         .node           = WREPL_NODE_B,
1320                         .is_static      = false,
1321                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1322                         .ips            = addresses_A_1,
1323                         .apply_expected = true
1324                 }
1325         },
1326
1327         /* 
1328          * unique,released vs. unique,tombstone
1329          * => should be replaced
1330          */
1331         {
1332                 .line   = __location__,
1333                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1334                 .r1     = {
1335                         .owner          = &ctx->a,
1336                         .type           = WREPL_TYPE_UNIQUE,
1337                         .state          = WREPL_STATE_RELEASED,
1338                         .node           = WREPL_NODE_B,
1339                         .is_static      = false,
1340                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1341                         .ips            = addresses_A_1,
1342                         .apply_expected = false
1343                 },
1344                 .r2     = {
1345                         .owner          = &ctx->b,
1346                         .type           = WREPL_TYPE_UNIQUE,
1347                         .state          = WREPL_STATE_TOMBSTONE,
1348                         .node           = WREPL_NODE_B,
1349                         .is_static      = false,
1350                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1351                         .ips            = addresses_B_1,
1352                         .apply_expected = true
1353                 }
1354         },
1355
1356         /* 
1357          * unique,tombstone vs. unique,active
1358          * => should be replaced
1359          */
1360         {
1361                 .line   = __location__,
1362                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1363                 .r1     = {
1364                         .owner          = &ctx->b,
1365                         .type           = WREPL_TYPE_UNIQUE,
1366                         .state          = WREPL_STATE_TOMBSTONE,
1367                         .node           = WREPL_NODE_B,
1368                         .is_static      = false,
1369                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1370                         .ips            = addresses_B_1,
1371                         .apply_expected = true
1372                 },
1373                 .r2     = {
1374                         .owner          = &ctx->a,
1375                         .type           = WREPL_TYPE_UNIQUE,
1376                         .state          = WREPL_STATE_ACTIVE,
1377                         .node           = WREPL_NODE_B,
1378                         .is_static      = false,
1379                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1380                         .ips            = addresses_A_1,
1381                         .apply_expected = true
1382                 }
1383         },
1384
1385         /* 
1386          * unique,tombstone vs. unique,tombstone
1387          * => should be replaced
1388          */
1389         {
1390                 .line   = __location__,
1391                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1392                 .r1     = {
1393                         .owner          = &ctx->a,
1394                         .type           = WREPL_TYPE_UNIQUE,
1395                         .state          = WREPL_STATE_TOMBSTONE,
1396                         .node           = WREPL_NODE_B,
1397                         .is_static      = false,
1398                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1399                         .ips            = addresses_A_1,
1400                         .apply_expected = true
1401                 },
1402                 .r2     = {
1403                         .owner          = &ctx->b,
1404                         .type           = WREPL_TYPE_UNIQUE,
1405                         .state          = WREPL_STATE_TOMBSTONE,
1406                         .node           = WREPL_NODE_B,
1407                         .is_static      = false,
1408                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1409                         .ips            = addresses_B_1,
1410                         .apply_expected = true
1411                 }
1412         },
1413
1414
1415 /*
1416  * unique vs normal groups section,
1417  */
1418         /* 
1419          * unique,active vs. group,active
1420          * => should be replaced
1421          */
1422         {
1423                 .line   = __location__,
1424                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1425                 .r1     = {
1426                         .owner          = &ctx->b,
1427                         .type           = WREPL_TYPE_UNIQUE,
1428                         .state          = WREPL_STATE_ACTIVE,
1429                         .node           = WREPL_NODE_B,
1430                         .is_static      = false,
1431                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1432                         .ips            = addresses_B_1,
1433                         .apply_expected = true
1434                 },
1435                 .r2     = {
1436                         .owner          = &ctx->a,
1437                         .type           = WREPL_TYPE_GROUP,
1438                         .state          = WREPL_STATE_ACTIVE,
1439                         .node           = WREPL_NODE_B,
1440                         .is_static      = false,
1441                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1442                         .ips            = addresses_A_1,
1443                         .apply_expected = true
1444                 }
1445         },
1446
1447         /* 
1448          * unique,active vs. group,tombstone
1449          * => should NOT be replaced
1450          */
1451         {
1452                 .line   = __location__,
1453                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1454                 .r1     = {
1455                         .owner          = &ctx->a,
1456                         .type           = WREPL_TYPE_UNIQUE,
1457                         .state          = WREPL_STATE_ACTIVE,
1458                         .node           = WREPL_NODE_B,
1459                         .is_static      = false,
1460                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1461                         .ips            = addresses_A_1,
1462                         .apply_expected = true
1463                 },
1464                 .r2     = {
1465                         .owner          = &ctx->b,
1466                         .type           = WREPL_TYPE_GROUP,
1467                         .state          = WREPL_STATE_TOMBSTONE,
1468                         .node           = WREPL_NODE_B,
1469                         .is_static      = false,
1470                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1471                         .ips            = addresses_A_1,
1472                         .apply_expected = false
1473                 }
1474         },
1475
1476         /* 
1477          * unique,released vs. group,active
1478          * => should be replaced
1479          */
1480         {
1481                 .line   = __location__,
1482                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1483                 .r1     = {
1484                         .owner          = &ctx->a,
1485                         .type           = WREPL_TYPE_UNIQUE,
1486                         .state          = WREPL_STATE_RELEASED,
1487                         .node           = WREPL_NODE_B,
1488                         .is_static      = false,
1489                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1490                         .ips            = addresses_A_1,
1491                         .apply_expected = false
1492                 },
1493                 .r2     = {
1494                         .owner          = &ctx->b,
1495                         .type           = WREPL_TYPE_GROUP,
1496                         .state          = WREPL_STATE_ACTIVE,
1497                         .node           = WREPL_NODE_B,
1498                         .is_static      = false,
1499                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1500                         .ips            = addresses_B_1,
1501                         .apply_expected = true
1502                 }
1503         },
1504
1505         /* 
1506          * unique,released vs. group,tombstone
1507          * => should be replaced
1508          */
1509         {
1510                 .line   = __location__,
1511                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1512                 .r1     = {
1513                         .owner          = &ctx->b,
1514                         .type           = WREPL_TYPE_UNIQUE,
1515                         .state          = WREPL_STATE_RELEASED,
1516                         .node           = WREPL_NODE_B,
1517                         .is_static      = false,
1518                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1519                         .ips            = addresses_B_1,
1520                         .apply_expected = false
1521                 },
1522                 .r2     = {
1523                         .owner          = &ctx->a,
1524                         .type           = WREPL_TYPE_GROUP,
1525                         .state          = WREPL_STATE_TOMBSTONE,
1526                         .node           = WREPL_NODE_B,
1527                         .is_static      = false,
1528                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1529                         .ips            = addresses_A_1,
1530                         .apply_expected = true
1531                 }
1532         },
1533
1534         /* 
1535          * unique,tombstone vs. group,active
1536          * => should be replaced
1537          */
1538         {
1539                 .line   = __location__,
1540                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1541                 .r1     = {
1542                         .owner          = &ctx->a,
1543                         .type           = WREPL_TYPE_UNIQUE,
1544                         .state          = WREPL_STATE_TOMBSTONE,
1545                         .node           = WREPL_NODE_B,
1546                         .is_static      = false,
1547                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1548                         .ips            = addresses_A_1,
1549                         .apply_expected = true
1550                 },
1551                 .r2     = {
1552                         .owner          = &ctx->b,
1553                         .type           = WREPL_TYPE_GROUP,
1554                         .state          = WREPL_STATE_ACTIVE,
1555                         .node           = WREPL_NODE_B,
1556                         .is_static      = false,
1557                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1558                         .ips            = addresses_B_1,
1559                         .apply_expected = true
1560                 }
1561         },
1562
1563         /* 
1564          * unique,tombstone vs. group,tombstone
1565          * => should be replaced
1566          */
1567         {
1568                 .line   = __location__,
1569                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1570                 .r1     = {
1571                         .owner          = &ctx->b,
1572                         .type           = WREPL_TYPE_UNIQUE,
1573                         .state          = WREPL_STATE_TOMBSTONE,
1574                         .node           = WREPL_NODE_B,
1575                         .is_static      = false,
1576                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1577                         .ips            = addresses_B_1,
1578                         .apply_expected = true
1579                 },
1580                 .r2     = {
1581                         .owner          = &ctx->a,
1582                         .type           = WREPL_TYPE_GROUP,
1583                         .state          = WREPL_STATE_TOMBSTONE,
1584                         .node           = WREPL_NODE_B,
1585                         .is_static      = false,
1586                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1587                         .ips            = addresses_A_1,
1588                         .apply_expected = true
1589                 }
1590         },
1591
1592 /*
1593  * unique vs special groups section,
1594  */
1595         /* 
1596          * unique,active vs. sgroup,active
1597          * => should NOT be replaced
1598          */
1599         {
1600                 .line   = __location__,
1601                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1602                 .r1     = {
1603                         .owner          = &ctx->a,
1604                         .type           = WREPL_TYPE_UNIQUE,
1605                         .state          = WREPL_STATE_ACTIVE,
1606                         .node           = WREPL_NODE_B,
1607                         .is_static      = false,
1608                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1609                         .ips            = addresses_A_1,
1610                         .apply_expected = true
1611                 },
1612                 .r2     = {
1613                         .owner          = &ctx->b,
1614                         .type           = WREPL_TYPE_SGROUP,
1615                         .state          = WREPL_STATE_ACTIVE,
1616                         .node           = WREPL_NODE_B,
1617                         .is_static      = false,
1618                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1619                         .ips            = addresses_A_1,
1620                         .apply_expected = false
1621                 }
1622         },
1623
1624         /* 
1625          * unique,active vs. sgroup,tombstone
1626          * => should NOT be replaced
1627          */
1628         {
1629                 .line   = __location__,
1630                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1631                 .r1     = {
1632                         .owner          = &ctx->a,
1633                         .type           = WREPL_TYPE_UNIQUE,
1634                         .state          = WREPL_STATE_ACTIVE,
1635                         .node           = WREPL_NODE_B,
1636                         .is_static      = false,
1637                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1638                         .ips            = addresses_A_1,
1639                         .apply_expected = true
1640                 },
1641                 .r2     = {
1642                         .owner          = &ctx->b,
1643                         .type           = WREPL_TYPE_SGROUP,
1644                         .state          = WREPL_STATE_TOMBSTONE,
1645                         .node           = WREPL_NODE_B,
1646                         .is_static      = false,
1647                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1648                         .ips            = addresses_A_1,
1649                         .apply_expected = false
1650                 }
1651         },
1652
1653         /* 
1654          * unique,released vs. sgroup,active
1655          * => should be replaced
1656          */
1657         {
1658                 .line   = __location__,
1659                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1660                 .r1     = {
1661                         .owner          = &ctx->a,
1662                         .type           = WREPL_TYPE_UNIQUE,
1663                         .state          = WREPL_STATE_RELEASED,
1664                         .node           = WREPL_NODE_B,
1665                         .is_static      = false,
1666                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1667                         .ips            = addresses_A_1,
1668                         .apply_expected = false
1669                 },
1670                 .r2     = {
1671                         .owner          = &ctx->b,
1672                         .type           = WREPL_TYPE_SGROUP,
1673                         .state          = WREPL_STATE_ACTIVE,
1674                         .node           = WREPL_NODE_B,
1675                         .is_static      = false,
1676                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1677                         .ips            = addresses_B_3_4,
1678                         .apply_expected = true
1679                 }
1680         },
1681
1682         /* 
1683          * unique,released vs. sgroup,tombstone
1684          * => should be replaced
1685          */
1686         {
1687                 .line   = __location__,
1688                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1689                 .r1     = {
1690                         .owner          = &ctx->b,
1691                         .type           = WREPL_TYPE_UNIQUE,
1692                         .state          = WREPL_STATE_RELEASED,
1693                         .node           = WREPL_NODE_B,
1694                         .is_static      = false,
1695                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1696                         .ips            = addresses_B_1,
1697                         .apply_expected = false
1698                 },
1699                 .r2     = {
1700                         .owner          = &ctx->a,
1701                         .type           = WREPL_TYPE_SGROUP,
1702                         .state          = WREPL_STATE_TOMBSTONE,
1703                         .node           = WREPL_NODE_B,
1704                         .is_static      = false,
1705                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1706                         .ips            = addresses_A_3_4,
1707                         .apply_expected = true
1708                 }
1709         },
1710
1711         /* 
1712          * unique,tombstone vs. sgroup,active
1713          * => should be replaced
1714          */
1715         {
1716                 .line   = __location__,
1717                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1718                 .r1     = {
1719                         .owner          = &ctx->a,
1720                         .type           = WREPL_TYPE_UNIQUE,
1721                         .state          = WREPL_STATE_TOMBSTONE,
1722                         .node           = WREPL_NODE_B,
1723                         .is_static      = false,
1724                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1725                         .ips            = addresses_A_1,
1726                         .apply_expected = true
1727                 },
1728                 .r2     = {
1729                         .owner          = &ctx->b,
1730                         .type           = WREPL_TYPE_SGROUP,
1731                         .state          = WREPL_STATE_ACTIVE,
1732                         .node           = WREPL_NODE_B,
1733                         .is_static      = false,
1734                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1735                         .ips            = addresses_B_3_4,
1736                         .apply_expected = true
1737                 }
1738         },
1739
1740         /* 
1741          * unique,tombstone vs. sgroup,tombstone
1742          * => should be replaced
1743          */
1744         {
1745                 .line   = __location__,
1746                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1747                 .r1     = {
1748                         .owner          = &ctx->b,
1749                         .type           = WREPL_TYPE_UNIQUE,
1750                         .state          = WREPL_STATE_TOMBSTONE,
1751                         .node           = WREPL_NODE_B,
1752                         .is_static      = false,
1753                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1754                         .ips            = addresses_B_1,
1755                         .apply_expected = true
1756                 },
1757                 .r2     = {
1758                         .owner          = &ctx->a,
1759                         .type           = WREPL_TYPE_SGROUP,
1760                         .state          = WREPL_STATE_TOMBSTONE,
1761                         .node           = WREPL_NODE_B,
1762                         .is_static      = false,
1763                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1764                         .ips            = addresses_A_3_4,
1765                         .apply_expected = true
1766                 }
1767         },
1768
1769 /*
1770  * unique vs multi homed section,
1771  */
1772         /* 
1773          * unique,active vs. mhomed,active
1774          * => should be replaced
1775          */
1776         {
1777                 .line   = __location__,
1778                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1779                 .r1     = {
1780                         .owner          = &ctx->a,
1781                         .type           = WREPL_TYPE_UNIQUE,
1782                         .state          = WREPL_STATE_ACTIVE,
1783                         .node           = WREPL_NODE_B,
1784                         .is_static      = false,
1785                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1786                         .ips            = addresses_A_1,
1787                         .apply_expected = true
1788                 },
1789                 .r2     = {
1790                         .owner          = &ctx->b,
1791                         .type           = WREPL_TYPE_MHOMED,
1792                         .state          = WREPL_STATE_ACTIVE,
1793                         .node           = WREPL_NODE_B,
1794                         .is_static      = false,
1795                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1796                         .ips            = addresses_B_3_4,
1797                         .apply_expected = true
1798                 }
1799         },
1800
1801         /* 
1802          * unique,active vs. mhomed,tombstone
1803          * => should NOT be replaced
1804          */
1805         {
1806                 .line   = __location__,
1807                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1808                 .r1     = {
1809                         .owner          = &ctx->b,
1810                         .type           = WREPL_TYPE_UNIQUE,
1811                         .state          = WREPL_STATE_ACTIVE,
1812                         .node           = WREPL_NODE_B,
1813                         .is_static      = false,
1814                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1815                         .ips            = addresses_B_3_4,
1816                         .apply_expected = true
1817                 },
1818                 .r2     = {
1819                         .owner          = &ctx->a,
1820                         .type           = WREPL_TYPE_MHOMED,
1821                         .state          = WREPL_STATE_TOMBSTONE,
1822                         .node           = WREPL_NODE_B,
1823                         .is_static      = false,
1824                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1825                         .ips            = addresses_B_3_4,
1826                         .apply_expected = false
1827                 }
1828         },
1829
1830         /* 
1831          * unique,released vs. mhomed,active
1832          * => should be replaced
1833          */
1834         {
1835                 .line   = __location__,
1836                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1837                 .r1     = {
1838                         .owner          = &ctx->b,
1839                         .type           = WREPL_TYPE_UNIQUE,
1840                         .state          = WREPL_STATE_RELEASED,
1841                         .node           = WREPL_NODE_B,
1842                         .is_static      = false,
1843                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1844                         .ips            = addresses_B_1,
1845                         .apply_expected = false
1846                 },
1847                 .r2     = {
1848                         .owner          = &ctx->a,
1849                         .type           = WREPL_TYPE_MHOMED,
1850                         .state          = WREPL_STATE_ACTIVE,
1851                         .node           = WREPL_NODE_B,
1852                         .is_static      = false,
1853                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1854                         .ips            = addresses_A_3_4,
1855                         .apply_expected = true
1856                 }
1857         },
1858
1859         /* 
1860          * unique,released vs. mhomed,tombstone
1861          * => should be replaced
1862          */
1863         {
1864                 .line   = __location__,
1865                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1866                 .r1     = {
1867                         .owner          = &ctx->a,
1868                         .type           = WREPL_TYPE_UNIQUE,
1869                         .state          = WREPL_STATE_RELEASED,
1870                         .node           = WREPL_NODE_B,
1871                         .is_static      = false,
1872                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1873                         .ips            = addresses_A_1,
1874                         .apply_expected = false
1875                 },
1876                 .r2     = {
1877                         .owner          = &ctx->b,
1878                         .type           = WREPL_TYPE_MHOMED,
1879                         .state          = WREPL_STATE_TOMBSTONE,
1880                         .node           = WREPL_NODE_B,
1881                         .is_static      = false,
1882                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1883                         .ips            = addresses_B_3_4,
1884                         .apply_expected = true
1885                 }
1886         },
1887
1888         /* 
1889          * unique,tombstone vs. mhomed,active
1890          * => should be replaced
1891          */
1892         {
1893                 .line   = __location__,
1894                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1895                 .r1     = {
1896                         .owner          = &ctx->b,
1897                         .type           = WREPL_TYPE_UNIQUE,
1898                         .state          = WREPL_STATE_TOMBSTONE,
1899                         .node           = WREPL_NODE_B,
1900                         .is_static      = false,
1901                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1902                         .ips            = addresses_B_1,
1903                         .apply_expected = true
1904                 },
1905                 .r2     = {
1906                         .owner          = &ctx->a,
1907                         .type           = WREPL_TYPE_MHOMED,
1908                         .state          = WREPL_STATE_ACTIVE,
1909                         .node           = WREPL_NODE_B,
1910                         .is_static      = false,
1911                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1912                         .ips            = addresses_A_3_4,
1913                         .apply_expected = true
1914                 }
1915         },
1916
1917         /* 
1918          * unique,tombstone vs. mhomed,tombstone
1919          * => should be replaced
1920          */
1921         {
1922                 .line   = __location__,
1923                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1924                 .r1     = {
1925                         .owner          = &ctx->a,
1926                         .type           = WREPL_TYPE_UNIQUE,
1927                         .state          = WREPL_STATE_TOMBSTONE,
1928                         .node           = WREPL_NODE_B,
1929                         .is_static      = false,
1930                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1931                         .ips            = addresses_A_1,
1932                         .apply_expected = true
1933                 },
1934                 .r2     = {
1935                         .owner          = &ctx->b,
1936                         .type           = WREPL_TYPE_MHOMED,
1937                         .state          = WREPL_STATE_TOMBSTONE,
1938                         .node           = WREPL_NODE_B,
1939                         .is_static      = false,
1940                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1941                         .ips            = addresses_B_3_4,
1942                         .apply_expected = true
1943                 }
1944         },
1945
1946 /*
1947  * normal groups vs unique section,
1948  */
1949         /* 
1950          * group,active vs. unique,active
1951          * => should NOT be replaced
1952          */
1953         {
1954                 .line   = __location__,
1955                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1956                 .r1     = {
1957                         .owner          = &ctx->a,
1958                         .type           = WREPL_TYPE_GROUP,
1959                         .state          = WREPL_STATE_ACTIVE,
1960                         .node           = WREPL_NODE_B,
1961                         .is_static      = false,
1962                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1963                         .ips            = addresses_A_1,
1964                         .apply_expected = true
1965                 },
1966                 .r2     = {
1967                         .owner          = &ctx->b,
1968                         .type           = WREPL_TYPE_UNIQUE,
1969                         .state          = WREPL_STATE_ACTIVE,
1970                         .node           = WREPL_NODE_B,
1971                         .is_static      = false,
1972                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1973                         .ips            = addresses_A_1,
1974                         .apply_expected = false
1975                 }
1976         },
1977
1978         /* 
1979          * group,active vs. unique,tombstone
1980          * => should NOT be replaced
1981          */
1982         {
1983                 .line   = __location__,
1984                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1985                 .r1     = {
1986                         .owner          = &ctx->a,
1987                         .type           = WREPL_TYPE_GROUP,
1988                         .state          = WREPL_STATE_ACTIVE,
1989                         .node           = WREPL_NODE_B,
1990                         .is_static      = false,
1991                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1992                         .ips            = addresses_A_1,
1993                         .apply_expected = true
1994                 },
1995                 .r2     = {
1996                         .owner          = &ctx->b,
1997                         .type           = WREPL_TYPE_UNIQUE,
1998                         .state          = WREPL_STATE_TOMBSTONE,
1999                         .node           = WREPL_NODE_B,
2000                         .is_static      = false,
2001                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2002                         .ips            = addresses_A_1,
2003                         .apply_expected = false
2004                 }
2005         },
2006
2007         /* 
2008          * group,released vs. unique,active
2009          * => should NOT be replaced
2010          */
2011         {
2012                 .line   = __location__,
2013                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2014                 .r1     = {
2015                         .owner          = &ctx->a,
2016                         .type           = WREPL_TYPE_GROUP,
2017                         .state          = WREPL_STATE_RELEASED,
2018                         .node           = WREPL_NODE_B,
2019                         .is_static      = false,
2020                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2021                         .ips            = addresses_A_1,
2022                         .apply_expected = false
2023                 },
2024                 .r2     = {
2025                         .owner          = &ctx->b,
2026                         .type           = WREPL_TYPE_UNIQUE,
2027                         .state          = WREPL_STATE_ACTIVE,
2028                         .node           = WREPL_NODE_B,
2029                         .is_static      = false,
2030                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2031                         .ips            = addresses_A_1,
2032                         .apply_expected = false
2033                 }
2034         },
2035
2036         /* 
2037          * group,released vs. unique,tombstone
2038          * => should NOT be replaced
2039          */
2040         {
2041                 .line   = __location__,
2042                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2043                 .r1     = {
2044                         .owner          = &ctx->a,
2045                         .type           = WREPL_TYPE_GROUP,
2046                         .state          = WREPL_STATE_RELEASED,
2047                         .node           = WREPL_NODE_B,
2048                         .is_static      = false,
2049                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2050                         .ips            = addresses_A_1,
2051                         .apply_expected = false
2052                 },
2053                 .r2     = {
2054                         .owner          = &ctx->b,
2055                         .type           = WREPL_TYPE_UNIQUE,
2056                         .state          = WREPL_STATE_TOMBSTONE,
2057                         .node           = WREPL_NODE_B,
2058                         .is_static      = false,
2059                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2060                         .ips            = addresses_A_1,
2061                         .apply_expected = false
2062                 }
2063         },
2064
2065         /* 
2066          * group,tombstone vs. unique,active
2067          * => should NOT be replaced
2068          */
2069         {
2070                 .line   = __location__,
2071                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2072                 .r1     = {
2073                         .owner          = &ctx->a,
2074                         .type           = WREPL_TYPE_GROUP,
2075                         .state          = WREPL_STATE_TOMBSTONE,
2076                         .node           = WREPL_NODE_B,
2077                         .is_static      = false,
2078                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2079                         .ips            = addresses_A_1,
2080                         .apply_expected = true
2081                 },
2082                 .r2     = {
2083                         .owner          = &ctx->b,
2084                         .type           = WREPL_TYPE_UNIQUE,
2085                         .state          = WREPL_STATE_ACTIVE,
2086                         .node           = WREPL_NODE_B,
2087                         .is_static      = false,
2088                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2089                         .ips            = addresses_A_1,
2090                         .apply_expected = false
2091                 }
2092         },
2093
2094         /* 
2095          * group,tombstone vs. unique,tombstone
2096          * => should NOT be replaced
2097          */
2098         {
2099                 .line   = __location__,
2100                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2101                 .r1     = {
2102                         .owner          = &ctx->a,
2103                         .type           = WREPL_TYPE_GROUP,
2104                         .state          = WREPL_STATE_TOMBSTONE,
2105                         .node           = WREPL_NODE_B,
2106                         .is_static      = false,
2107                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2108                         .ips            = addresses_A_1,
2109                         .apply_expected = true
2110                 },
2111                 .r2     = {
2112                         .owner          = &ctx->b,
2113                         .type           = WREPL_TYPE_UNIQUE,
2114                         .state          = WREPL_STATE_TOMBSTONE,
2115                         .node           = WREPL_NODE_B,
2116                         .is_static      = false,
2117                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2118                         .ips            = addresses_A_1,
2119                         .apply_expected = false
2120                 }
2121         },
2122
2123 /*
2124  * normal groups vs normal groups section,
2125  */
2126         /* 
2127          * group,active vs. group,active
2128          * => should NOT be replaced
2129          */
2130         {
2131                 .line   = __location__,
2132                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2133                 .r1     = {
2134                         .owner          = &ctx->a,
2135                         .type           = WREPL_TYPE_GROUP,
2136                         .state          = WREPL_STATE_ACTIVE,
2137                         .node           = WREPL_NODE_B,
2138                         .is_static      = false,
2139                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2140                         .ips            = addresses_A_1,
2141                         .apply_expected = true
2142                 },
2143                 .r2     = {
2144                         .owner          = &ctx->b,
2145                         .type           = WREPL_TYPE_GROUP,
2146                         .state          = WREPL_STATE_ACTIVE,
2147                         .node           = WREPL_NODE_B,
2148                         .is_static      = false,
2149                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2150                         .ips            = addresses_A_1,
2151                         .apply_expected = false
2152                 }
2153         },
2154
2155         /* 
2156          * group,active vs. group,tombstone
2157          * => should NOT be replaced
2158          */
2159         {
2160                 .line   = __location__,
2161                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2162                 .r1     = {
2163                         .owner          = &ctx->a,
2164                         .type           = WREPL_TYPE_GROUP,
2165                         .state          = WREPL_STATE_ACTIVE,
2166                         .node           = WREPL_NODE_B,
2167                         .is_static      = false,
2168                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2169                         .ips            = addresses_A_1,
2170                         .apply_expected = true
2171                 },
2172                 .r2     = {
2173                         .owner          = &ctx->b,
2174                         .type           = WREPL_TYPE_GROUP,
2175                         .state          = WREPL_STATE_TOMBSTONE,
2176                         .node           = WREPL_NODE_B,
2177                         .is_static      = false,
2178                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2179                         .ips            = addresses_A_1,
2180                         .apply_expected = false
2181                 }
2182         },
2183
2184         /* 
2185          * group,released vs. group,active
2186          * => should be replaced
2187          */
2188         {
2189                 .line   = __location__,
2190                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2191                 .r1     = {
2192                         .owner          = &ctx->a,
2193                         .type           = WREPL_TYPE_GROUP,
2194                         .state          = WREPL_STATE_RELEASED,
2195                         .node           = WREPL_NODE_B,
2196                         .is_static      = false,
2197                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2198                         .ips            = addresses_A_1,
2199                         .apply_expected = false
2200                 },
2201                 .r2     = {
2202                         .owner          = &ctx->b,
2203                         .type           = WREPL_TYPE_GROUP,
2204                         .state          = WREPL_STATE_ACTIVE,
2205                         .node           = WREPL_NODE_B,
2206                         .is_static      = false,
2207                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2208                         .ips            = addresses_B_1,
2209                         .apply_expected = true
2210                 }
2211         },
2212
2213         /* 
2214          * group,released vs. group,tombstone
2215          * => should be replaced
2216          */
2217         {
2218                 .line   = __location__,
2219                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2220                 .r1     = {
2221                         .owner          = &ctx->a,
2222                         .type           = WREPL_TYPE_GROUP,
2223                         .state          = WREPL_STATE_RELEASED,
2224                         .node           = WREPL_NODE_B,
2225                         .is_static      = false,
2226                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2227                         .ips            = addresses_A_1,
2228                         .apply_expected = false
2229                 },
2230                 .r2     = {
2231                         .owner          = &ctx->b,
2232                         .type           = WREPL_TYPE_GROUP,
2233                         .state          = WREPL_STATE_TOMBSTONE,
2234                         .node           = WREPL_NODE_B,
2235                         .is_static      = false,
2236                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2237                         .ips            = addresses_B_1,
2238                         .apply_expected = true
2239                 }
2240         },
2241
2242         /* 
2243          * group,tombstone vs. group,active
2244          * => should be replaced
2245          */
2246         {
2247                 .line   = __location__,
2248                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2249                 .r1     = {
2250                         .owner          = &ctx->b,
2251                         .type           = WREPL_TYPE_GROUP,
2252                         .state          = WREPL_STATE_TOMBSTONE,
2253                         .node           = WREPL_NODE_B,
2254                         .is_static      = false,
2255                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2256                         .ips            = addresses_B_1,
2257                         .apply_expected = true
2258                 },
2259                 .r2     = {
2260                         .owner          = &ctx->a,
2261                         .type           = WREPL_TYPE_GROUP,
2262                         .state          = WREPL_STATE_ACTIVE,
2263                         .node           = WREPL_NODE_B,
2264                         .is_static      = false,
2265                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2266                         .ips            = addresses_A_1,
2267                         .apply_expected = true
2268                 }
2269         },
2270
2271         /* 
2272          * group,tombstone vs. group,tombstone
2273          * => should be replaced
2274          */
2275         {
2276                 .line   = __location__,
2277                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2278                 .r1     = {
2279                         .owner          = &ctx->a,
2280                         .type           = WREPL_TYPE_GROUP,
2281                         .state          = WREPL_STATE_TOMBSTONE,
2282                         .node           = WREPL_NODE_B,
2283                         .is_static      = false,
2284                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2285                         .ips            = addresses_A_1,
2286                         .apply_expected = true
2287                 },
2288                 .r2     = {
2289                         .owner          = &ctx->b,
2290                         .type           = WREPL_TYPE_GROUP,
2291                         .state          = WREPL_STATE_TOMBSTONE,
2292                         .node           = WREPL_NODE_B,
2293                         .is_static      = false,
2294                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2295                         .ips            = addresses_B_1,
2296                         .apply_expected = true
2297                 }
2298         },
2299
2300 /*
2301  * normal groups vs special groups section,
2302  */
2303         /* 
2304          * group,active vs. sgroup,active
2305          * => should NOT be replaced
2306          */
2307         {
2308                 .line   = __location__,
2309                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2310                 .r1     = {
2311                         .owner          = &ctx->b,
2312                         .type           = WREPL_TYPE_GROUP,
2313                         .state          = WREPL_STATE_ACTIVE,
2314                         .node           = WREPL_NODE_B,
2315                         .is_static      = false,
2316                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2317                         .ips            = addresses_B_1,
2318                         .apply_expected = true
2319                 },
2320                 .r2     = {
2321                         .owner          = &ctx->a,
2322                         .type           = WREPL_TYPE_SGROUP,
2323                         .state          = WREPL_STATE_ACTIVE,
2324                         .node           = WREPL_NODE_B,
2325                         .is_static      = false,
2326                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2327                         .ips            = addresses_B_1,
2328                         .apply_expected = false
2329                 }
2330         },
2331
2332         /* 
2333          * group,active vs. sgroup,tombstone
2334          * => should NOT be replaced
2335          */
2336         {
2337                 .line   = __location__,
2338                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2339                 .r1     = {
2340                         .owner          = &ctx->b,
2341                         .type           = WREPL_TYPE_GROUP,
2342                         .state          = WREPL_STATE_ACTIVE,
2343                         .node           = WREPL_NODE_B,
2344                         .is_static      = false,
2345                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2346                         .ips            = addresses_B_1,
2347                         .apply_expected = true
2348                 },
2349                 .r2     = {
2350                         .owner          = &ctx->a,
2351                         .type           = WREPL_TYPE_SGROUP,
2352                         .state          = WREPL_STATE_TOMBSTONE,
2353                         .node           = WREPL_NODE_B,
2354                         .is_static      = false,
2355                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2356                         .ips            = addresses_B_1,
2357                         .apply_expected = false
2358                 }
2359         },
2360
2361         /* 
2362          * group,released vs. sgroup,active
2363          * => should be replaced
2364          */
2365         {
2366                 .line   = __location__,
2367                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2368                 .r1     = {
2369                         .owner          = &ctx->a,
2370                         .type           = WREPL_TYPE_GROUP,
2371                         .state          = WREPL_STATE_RELEASED,
2372                         .node           = WREPL_NODE_B,
2373                         .is_static      = false,
2374                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2375                         .ips            = addresses_A_1,
2376                         .apply_expected = false
2377                 },
2378                 .r2     = {
2379                         .owner          = &ctx->b,
2380                         .type           = WREPL_TYPE_SGROUP,
2381                         .state          = WREPL_STATE_ACTIVE,
2382                         .node           = WREPL_NODE_B,
2383                         .is_static      = false,
2384                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2385                         .ips            = addresses_B_1,
2386                         .apply_expected = true
2387                 }
2388         },
2389
2390         /* 
2391          * group,released vs. sgroup,tombstone
2392          * => should NOT be replaced
2393          */
2394         {
2395                 .line   = __location__,
2396                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2397                 .r1     = {
2398                         .owner          = &ctx->b,
2399                         .type           = WREPL_TYPE_GROUP,
2400                         .state          = WREPL_STATE_RELEASED,
2401                         .node           = WREPL_NODE_B,
2402                         .is_static      = false,
2403                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2404                         .ips            = addresses_B_1,
2405                         .apply_expected = false
2406                 },
2407                 .r2     = {
2408                         .owner          = &ctx->a,
2409                         .type           = WREPL_TYPE_SGROUP,
2410                         .state          = WREPL_STATE_TOMBSTONE,
2411                         .node           = WREPL_NODE_B,
2412                         .is_static      = false,
2413                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2414                         .ips            = addresses_B_1,
2415                         .apply_expected = false
2416                 }
2417         },
2418
2419         /* 
2420          * group,tombstone vs. sgroup,active
2421          * => should be replaced
2422          */
2423         {
2424                 .line   = __location__,
2425                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2426                 .r1     = {
2427                         .owner          = &ctx->b,
2428                         .type           = WREPL_TYPE_GROUP,
2429                         .state          = WREPL_STATE_TOMBSTONE,
2430                         .node           = WREPL_NODE_B,
2431                         .is_static      = false,
2432                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2433                         .ips            = addresses_B_1,
2434                         .apply_expected = true
2435                 },
2436                 .r2     = {
2437                         .owner          = &ctx->a,
2438                         .type           = WREPL_TYPE_SGROUP,
2439                         .state          = WREPL_STATE_ACTIVE,
2440                         .node           = WREPL_NODE_B,
2441                         .is_static      = false,
2442                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2443                         .ips            = addresses_A_1,
2444                         .apply_expected = true
2445                 }
2446         },
2447
2448         /* 
2449          * group,tombstone vs. sgroup,tombstone
2450          * => should be replaced
2451          */
2452         {
2453                 .line   = __location__,
2454                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2455                 .r1     = {
2456                         .owner          = &ctx->a,
2457                         .type           = WREPL_TYPE_GROUP,
2458                         .state          = WREPL_STATE_TOMBSTONE,
2459                         .node           = WREPL_NODE_B,
2460                         .is_static      = false,
2461                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2462                         .ips            = addresses_A_1,
2463                         .apply_expected = true
2464                 },
2465                 .r2     = {
2466                         .owner          = &ctx->b,
2467                         .type           = WREPL_TYPE_SGROUP,
2468                         .state          = WREPL_STATE_TOMBSTONE,
2469                         .node           = WREPL_NODE_B,
2470                         .is_static      = false,
2471                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2472                         .ips            = addresses_B_1,
2473                         .apply_expected = true
2474                 }
2475         },
2476
2477 /*
2478  * normal groups vs multi homed section,
2479  */
2480         /* 
2481          * group,active vs. mhomed,active
2482          * => should NOT be replaced
2483          */
2484         {
2485                 .line   = __location__,
2486                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2487                 .r1     = {
2488                         .owner          = &ctx->b,
2489                         .type           = WREPL_TYPE_GROUP,
2490                         .state          = WREPL_STATE_ACTIVE,
2491                         .node           = WREPL_NODE_B,
2492                         .is_static      = false,
2493                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2494                         .ips            = addresses_B_1,
2495                         .apply_expected = true
2496                 },
2497                 .r2     = {
2498                         .owner          = &ctx->a,
2499                         .type           = WREPL_TYPE_MHOMED,
2500                         .state          = WREPL_STATE_ACTIVE,
2501                         .node           = WREPL_NODE_B,
2502                         .is_static      = false,
2503                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2504                         .ips            = addresses_B_1,
2505                         .apply_expected = false
2506                 }
2507         },
2508
2509         /* 
2510          * group,active vs. mhomed,tombstone
2511          * => should NOT be replaced
2512          */
2513         {
2514                 .line   = __location__,
2515                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2516                 .r1     = {
2517                         .owner          = &ctx->b,
2518                         .type           = WREPL_TYPE_GROUP,
2519                         .state          = WREPL_STATE_ACTIVE,
2520                         .node           = WREPL_NODE_B,
2521                         .is_static      = false,
2522                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2523                         .ips            = addresses_B_1,
2524                         .apply_expected = true
2525                 },
2526                 .r2     = {
2527                         .owner          = &ctx->a,
2528                         .type           = WREPL_TYPE_MHOMED,
2529                         .state          = WREPL_STATE_TOMBSTONE,
2530                         .node           = WREPL_NODE_B,
2531                         .is_static      = false,
2532                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2533                         .ips            = addresses_B_1,
2534                         .apply_expected = false
2535                 }
2536         },
2537
2538         /* 
2539          * group,released vs. mhomed,active
2540          * => should NOT be replaced
2541          */
2542         {
2543                 .line   = __location__,
2544                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2545                 .r1     = {
2546                         .owner          = &ctx->b,
2547                         .type           = WREPL_TYPE_GROUP,
2548                         .state          = WREPL_STATE_RELEASED,
2549                         .node           = WREPL_NODE_B,
2550                         .is_static      = false,
2551                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2552                         .ips            = addresses_B_1,
2553                         .apply_expected = false
2554                 },
2555                 .r2     = {
2556                         .owner          = &ctx->a,
2557                         .type           = WREPL_TYPE_MHOMED,
2558                         .state          = WREPL_STATE_ACTIVE,
2559                         .node           = WREPL_NODE_B,
2560                         .is_static      = false,
2561                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2562                         .ips            = addresses_B_1,
2563                         .apply_expected = false
2564                 }
2565         },
2566
2567         /* 
2568          * group,released vs. mhomed,tombstone
2569          * => should NOT be replaced
2570          */
2571         {
2572                 .line   = __location__,
2573                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2574                 .r1     = {
2575                         .owner          = &ctx->b,
2576                         .type           = WREPL_TYPE_GROUP,
2577                         .state          = WREPL_STATE_RELEASED,
2578                         .node           = WREPL_NODE_B,
2579                         .is_static      = false,
2580                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2581                         .ips            = addresses_B_1,
2582                         .apply_expected = false
2583                 },
2584                 .r2     = {
2585                         .owner          = &ctx->a,
2586                         .type           = WREPL_TYPE_MHOMED,
2587                         .state          = WREPL_STATE_TOMBSTONE,
2588                         .node           = WREPL_NODE_B,
2589                         .is_static      = false,
2590                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2591                         .ips            = addresses_B_1,
2592                         .apply_expected = false
2593                 }
2594         },
2595
2596         /* 
2597          * group,tombstone vs. mhomed,active
2598          * => should be replaced
2599          */
2600         {
2601                 .line   = __location__,
2602                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2603                 .r1     = {
2604                         .owner          = &ctx->b,
2605                         .type           = WREPL_TYPE_GROUP,
2606                         .state          = WREPL_STATE_TOMBSTONE,
2607                         .node           = WREPL_NODE_B,
2608                         .is_static      = false,
2609                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2610                         .ips            = addresses_B_1,
2611                         .apply_expected = true
2612                 },
2613                 .r2     = {
2614                         .owner          = &ctx->a,
2615                         .type           = WREPL_TYPE_MHOMED,
2616                         .state          = WREPL_STATE_ACTIVE,
2617                         .node           = WREPL_NODE_B,
2618                         .is_static      = false,
2619                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2620                         .ips            = addresses_A_1,
2621                         .apply_expected = true
2622                 }
2623         },
2624
2625         /* 
2626          * group,tombstone vs. mhomed,tombstone
2627          * => should be replaced
2628          */
2629         {
2630                 .line   = __location__,
2631                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2632                 .r1     = {
2633                         .owner          = &ctx->a,
2634                         .type           = WREPL_TYPE_GROUP,
2635                         .state          = WREPL_STATE_TOMBSTONE,
2636                         .node           = WREPL_NODE_B,
2637                         .is_static      = false,
2638                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2639                         .ips            = addresses_A_1,
2640                         .apply_expected = true
2641                 },
2642                 .r2     = {
2643                         .owner          = &ctx->b,
2644                         .type           = WREPL_TYPE_MHOMED,
2645                         .state          = WREPL_STATE_TOMBSTONE,
2646                         .node           = WREPL_NODE_B,
2647                         .is_static      = false,
2648                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2649                         .ips            = addresses_B_1,
2650                         .apply_expected = true
2651                 }
2652         },
2653
2654 /*
2655  * special groups vs unique section,
2656  */
2657         /* 
2658          * sgroup,active vs. unique,active
2659          * => should NOT be replaced
2660          */
2661         {
2662                 .line   = __location__,
2663                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2664                 .r1     = {
2665                         .owner          = &ctx->b,
2666                         .type           = WREPL_TYPE_SGROUP,
2667                         .state          = WREPL_STATE_ACTIVE,
2668                         .node           = WREPL_NODE_B,
2669                         .is_static      = false,
2670                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2671                         .ips            = addresses_B_1,
2672                         .apply_expected = true
2673                 },
2674                 .r2     = {
2675                         .owner          = &ctx->a,
2676                         .type           = WREPL_TYPE_UNIQUE,
2677                         .state          = WREPL_STATE_ACTIVE,
2678                         .node           = WREPL_NODE_B,
2679                         .is_static      = false,
2680                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2681                         .ips            = addresses_B_1,
2682                         .apply_expected = false
2683                 }
2684         },
2685
2686         /* 
2687          * sgroup,active vs. unique,tombstone
2688          * => should NOT be replaced
2689          */
2690         {
2691                 .line   = __location__,
2692                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2693                 .r1     = {
2694                         .owner          = &ctx->b,
2695                         .type           = WREPL_TYPE_SGROUP,
2696                         .state          = WREPL_STATE_ACTIVE,
2697                         .node           = WREPL_NODE_B,
2698                         .is_static      = false,
2699                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2700                         .ips            = addresses_B_1,
2701                         .apply_expected = true
2702                 },
2703                 .r2     = {
2704                         .owner          = &ctx->a,
2705                         .type           = WREPL_TYPE_UNIQUE,
2706                         .state          = WREPL_STATE_TOMBSTONE,
2707                         .node           = WREPL_NODE_B,
2708                         .is_static      = false,
2709                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2710                         .ips            = addresses_B_1,
2711                         .apply_expected = false
2712                 }
2713         },
2714
2715         /* 
2716          * sgroup,released vs. unique,active
2717          * => should be replaced
2718          */
2719         {
2720                 .line   = __location__,
2721                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2722                 .r1     = {
2723                         .owner          = &ctx->b,
2724                         .type           = WREPL_TYPE_SGROUP,
2725                         .state          = WREPL_STATE_RELEASED,
2726                         .node           = WREPL_NODE_B,
2727                         .is_static      = false,
2728                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2729                         .ips            = addresses_B_1,
2730                         .apply_expected = false
2731                 },
2732                 .r2     = {
2733                         .owner          = &ctx->a,
2734                         .type           = WREPL_TYPE_UNIQUE,
2735                         .state          = WREPL_STATE_ACTIVE,
2736                         .node           = WREPL_NODE_B,
2737                         .is_static      = false,
2738                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2739                         .ips            = addresses_A_1,
2740                         .apply_expected = true
2741                 }
2742         },
2743
2744         /* 
2745          * sgroup,released vs. unique,tombstone
2746          * => should be replaced
2747          */
2748         {
2749                 .line   = __location__,
2750                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2751                 .r1     = {
2752                         .owner          = &ctx->a,
2753                         .type           = WREPL_TYPE_SGROUP,
2754                         .state          = WREPL_STATE_RELEASED,
2755                         .node           = WREPL_NODE_B,
2756                         .is_static      = false,
2757                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2758                         .ips            = addresses_A_1,
2759                         .apply_expected = false
2760                 },
2761                 .r2     = {
2762                         .owner          = &ctx->b,
2763                         .type           = WREPL_TYPE_UNIQUE,
2764                         .state          = WREPL_STATE_TOMBSTONE,
2765                         .node           = WREPL_NODE_B,
2766                         .is_static      = false,
2767                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2768                         .ips            = addresses_B_1,
2769                         .apply_expected = true
2770                 }
2771         },
2772
2773         /* 
2774          * sgroup,tombstone vs. unique,active
2775          * => should be replaced
2776          */
2777         {
2778                 .line   = __location__,
2779                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2780                 .r1     = {
2781                         .owner          = &ctx->a,
2782                         .type           = WREPL_TYPE_SGROUP,
2783                         .state          = WREPL_STATE_TOMBSTONE,
2784                         .node           = WREPL_NODE_B,
2785                         .is_static      = false,
2786                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2787                         .ips            = addresses_A_1,
2788                         .apply_expected = true
2789                 },
2790                 .r2     = {
2791                         .owner          = &ctx->b,
2792                         .type           = WREPL_TYPE_UNIQUE,
2793                         .state          = WREPL_STATE_ACTIVE,
2794                         .node           = WREPL_NODE_B,
2795                         .is_static      = false,
2796                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2797                         .ips            = addresses_B_1,
2798                         .apply_expected = true
2799                 }
2800         },
2801
2802         /* 
2803          * sgroup,tombstone vs. unique,tombstone
2804          * => should be replaced
2805          */
2806         {
2807                 .line   = __location__,
2808                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2809                 .r1     = {
2810                         .owner          = &ctx->b,
2811                         .type           = WREPL_TYPE_SGROUP,
2812                         .state          = WREPL_STATE_TOMBSTONE,
2813                         .node           = WREPL_NODE_B,
2814                         .is_static      = false,
2815                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2816                         .ips            = addresses_B_1,
2817                         .apply_expected = true
2818                 },
2819                 .r2     = {
2820                         .owner          = &ctx->a,
2821                         .type           = WREPL_TYPE_UNIQUE,
2822                         .state          = WREPL_STATE_TOMBSTONE,
2823                         .node           = WREPL_NODE_B,
2824                         .is_static      = false,
2825                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2826                         .ips            = addresses_A_1,
2827                         .apply_expected = true
2828                 }
2829         },
2830
2831 /*
2832  * special groups vs normal group section,
2833  */
2834         /* 
2835          * sgroup,active vs. group,active
2836          * => should NOT be replaced
2837          */
2838         {
2839                 .line   = __location__,
2840                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2841                 .r1     = {
2842                         .owner          = &ctx->a,
2843                         .type           = WREPL_TYPE_SGROUP,
2844                         .state          = WREPL_STATE_ACTIVE,
2845                         .node           = WREPL_NODE_B,
2846                         .is_static      = false,
2847                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2848                         .ips            = addresses_A_1,
2849                         .apply_expected = true
2850                 },
2851                 .r2     = {
2852                         .owner          = &ctx->b,
2853                         .type           = WREPL_TYPE_GROUP,
2854                         .state          = WREPL_STATE_ACTIVE,
2855                         .node           = WREPL_NODE_B,
2856                         .is_static      = false,
2857                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2858                         .ips            = addresses_A_1,
2859                         .apply_expected = false
2860                 }
2861         },
2862
2863         /* 
2864          * sgroup,active vs. group,tombstone
2865          * => should NOT be replaced
2866          */
2867         {
2868                 .line   = __location__,
2869                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2870                 .r1     = {
2871                         .owner          = &ctx->a,
2872                         .type           = WREPL_TYPE_SGROUP,
2873                         .state          = WREPL_STATE_ACTIVE,
2874                         .node           = WREPL_NODE_B,
2875                         .is_static      = false,
2876                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2877                         .ips            = addresses_A_1,
2878                         .apply_expected = true
2879                 },
2880                 .r2     = {
2881                         .owner          = &ctx->b,
2882                         .type           = WREPL_TYPE_GROUP,
2883                         .state          = WREPL_STATE_TOMBSTONE,
2884                         .node           = WREPL_NODE_B,
2885                         .is_static      = false,
2886                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2887                         .ips            = addresses_A_1,
2888                         .apply_expected = false
2889                 }
2890         },
2891
2892         /* 
2893          * sgroup,released vs. group,active
2894          * => should be replaced
2895          */
2896         {
2897                 .line   = __location__,
2898                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2899                 .r1     = {
2900                         .owner          = &ctx->a,
2901                         .type           = WREPL_TYPE_SGROUP,
2902                         .state          = WREPL_STATE_RELEASED,
2903                         .node           = WREPL_NODE_B,
2904                         .is_static      = false,
2905                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2906                         .ips            = addresses_A_1,
2907                         .apply_expected = false
2908                 },
2909                 .r2     = {
2910                         .owner          = &ctx->b,
2911                         .type           = WREPL_TYPE_GROUP,
2912                         .state          = WREPL_STATE_ACTIVE,
2913                         .node           = WREPL_NODE_B,
2914                         .is_static      = false,
2915                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2916                         .ips            = addresses_B_1,
2917                         .apply_expected = true
2918                 }
2919         },
2920
2921         /* 
2922          * sgroup,released vs. group,tombstone
2923          * => should be replaced
2924          */
2925         {
2926                 .line   = __location__,
2927                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2928                 .r1     = {
2929                         .owner          = &ctx->b,
2930                         .type           = WREPL_TYPE_SGROUP,
2931                         .state          = WREPL_STATE_RELEASED,
2932                         .node           = WREPL_NODE_B,
2933                         .is_static      = false,
2934                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2935                         .ips            = addresses_B_1,
2936                         .apply_expected = false
2937                 },
2938                 .r2     = {
2939                         .owner          = &ctx->a,
2940                         .type           = WREPL_TYPE_GROUP,
2941                         .state          = WREPL_STATE_TOMBSTONE,
2942                         .node           = WREPL_NODE_B,
2943                         .is_static      = false,
2944                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2945                         .ips            = addresses_A_1,
2946                         .apply_expected = true
2947                 }
2948         },
2949
2950         /* 
2951          * sgroup,tombstone vs. group,active
2952          * => should NOT be replaced
2953          */
2954         {
2955                 .line   = __location__,
2956                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2957                 .r1     = {
2958                         .owner          = &ctx->a,
2959                         .type           = WREPL_TYPE_SGROUP,
2960                         .state          = WREPL_STATE_TOMBSTONE,
2961                         .node           = WREPL_NODE_B,
2962                         .is_static      = false,
2963                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2964                         .ips            = addresses_A_1,
2965                         .apply_expected = true
2966                 },
2967                 .r2     = {
2968                         .owner          = &ctx->b,
2969                         .type           = WREPL_TYPE_GROUP,
2970                         .state          = WREPL_STATE_ACTIVE,
2971                         .node           = WREPL_NODE_B,
2972                         .is_static      = false,
2973                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2974                         .ips            = addresses_B_1,
2975                         .apply_expected = true
2976                 }
2977         },
2978
2979         /* 
2980          * sgroup,tombstone vs. group,tombstone
2981          * => should NOT be replaced
2982          */
2983         {
2984                 .line   = __location__,
2985                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2986                 .r1     = {
2987                         .owner          = &ctx->b,
2988                         .type           = WREPL_TYPE_SGROUP,
2989                         .state          = WREPL_STATE_TOMBSTONE,
2990                         .node           = WREPL_NODE_B,
2991                         .is_static      = false,
2992                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2993                         .ips            = addresses_B_1,
2994                         .apply_expected = true
2995                 },
2996                 .r2     = {
2997                         .owner          = &ctx->a,
2998                         .type           = WREPL_TYPE_GROUP,
2999                         .state          = WREPL_STATE_TOMBSTONE,
3000                         .node           = WREPL_NODE_B,
3001                         .is_static      = false,
3002                         .num_ips        = ARRAY_SIZE(addresses_A_1),
3003                         .ips            = addresses_A_1,
3004                         .apply_expected = true
3005                 }
3006         },
3007
3008 /*
3009  * special groups (not active) vs special group section,
3010  */
3011         /* 
3012          * sgroup,released vs. sgroup,active
3013          * => should be replaced
3014          */
3015         {
3016                 .line   = __location__,
3017                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
3018                 .r1     = {
3019                         .owner          = &ctx->a,
3020                         .type           = WREPL_TYPE_SGROUP,
3021                         .state          = WREPL_STATE_RELEASED,
3022                         .node           = WREPL_NODE_B,
3023                         .is_static      = false,
3024                         .num_ips        = ARRAY_SIZE(addresses_A_1),
3025                         .ips            = addresses_A_1,
3026                         .apply_expected = false
3027                 },
3028                 .r2     = {
3029                         .owner          = &ctx->b,
3030                         .type           = WREPL_TYPE_SGROUP,
3031                         .state          = WREPL_STATE_ACTIVE,
3032                         .node           = WREPL_NODE_B,
3033                         .is_static      = false,
3034                         .num_ips        = ARRAY_SIZE(addresses_B_1),
3035                         .ips            = addresses_B_1,
3036                         .apply_expected = true
3037                 }
3038         },
3039
3040         /* 
3041          * sgroup,released vs. sgroup,tombstone
3042          * => should be replaced
3043          */
3044         {
3045                 .line   = __location__,
3046                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
3047                 .r1     = {
3048                         .owner          = &ctx->b,
3049                         .type           = WREPL_TYPE_SGROUP,
3050                         .state          = WREPL_STATE_RELEASED,
3051                         .node           = WREPL_NODE_B,
3052                         .is_static      = false,
3053                         .num_ips        = ARRAY_SIZE(addresses_B_1),
3054                         .ips            = addresses_B_1,
3055                         .apply_expected = false
3056                 },
3057                 .r2     = {
3058                         .owner          = &ctx->a,
3059                         .type           = WREPL_TYPE_SGROUP,
3060                         .state          = WREPL_STATE_TOMBSTONE,
3061                         .node           = WREPL_NODE_B,
3062                         .is_static      = false,
3063                         .num_ips        = ARRAY_SIZE(addresses_A_1),
3064                         .ips            = addresses_A_1,
3065                         .apply_expected = true
3066                 }
3067         },
3068
3069         /* 
3070          * sgroup,tombstone vs. sgroup,active
3071          * => should NOT be replaced
3072          */
3073         {
3074                 .line   = __location__,
3075                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
3076                 .r1     = {
3077                         .owner          = &ctx->a,
3078                         .type           = WREPL_TYPE_SGROUP,
3079                         .state          = WREPL_STATE_TOMBSTONE,
3080                         .node           = WREPL_NODE_B,
3081                         .is_static      = false,
3082                         .num_ips        = ARRAY_SIZE(addresses_A_1),
3083                         .ips            = addresses_A_1,
3084                         .apply_expected = true
3085                 },
3086                 .r2     = {
3087                         .owner          = &ctx->b,
3088                         .type           = WREPL_TYPE_SGROUP,
3089                         .state          = WREPL_STATE_ACTIVE,
3090                         .node           = WREPL_NODE_B,
3091                         .is_static      = false,
3092                         .num_ips        = ARRAY_SIZE(addresses_B_1),
3093                         .ips            = addresses_B_1,
3094                         .apply_expected = true
3095                 }
3096         },
3097
3098         /* 
3099          * sgroup,tombstone vs. sgroup,tombstone
3100          * => should NOT be replaced
3101          */
3102         {
3103                 .line   = __location__,
3104                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
3105                 .r1     = {
3106                         .owner          = &ctx->b,
3107                         .type           = WREPL_TYPE_SGROUP,
3108                         .state          = WREPL_STATE_TOMBSTONE,
3109                         .node           = WREPL_NODE_B,
3110                         .is_static      = false,
3111                         .num_ips        = ARRAY_SIZE(addresses_B_1),
3112                         .ips            = addresses_B_1,
3113                         .apply_expected = true
3114                 },
3115                 .r2     = {
3116                         .owner          = &ctx->a,
3117                         .type           = WREPL_TYPE_SGROUP,
3118                         .state          = WREPL_STATE_TOMBSTONE,
3119                         .node           = WREPL_NODE_B,
3120                         .is_static      = false,
3121                         .num_ips        = ARRAY_SIZE(addresses_A_1),
3122                         .ips            = addresses_A_1,
3123                         .apply_expected = true
3124                 }
3125         },
3126
3127 /*
3128  * special groups vs multi homed section,
3129  */
3130         /* 
3131          * sgroup,active vs. mhomed,active
3132          * => should NOT be replaced
3133          */
3134         {
3135        &nb