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