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