r11144: - add special group vs. normal group section
[tprouty/samba.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;
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         pull_table.in.assoc_ctx = ctx->pull_assoc;
413         status = wrepl_pull_table(ctx->pull, ctx->pull, &pull_table);
414         if (!NT_STATUS_IS_OK(status)) return NULL;
415
416         for (i=0; i < pull_table.out.num_partners; i++) {
417                 if (strcmp(TEST_OWNER_A_ADDRESS,pull_table.out.partners[i].address)==0) {
418                         ctx->a.max_version      = pull_table.out.partners[i].max_version;
419                         ctx->a.min_version      = pull_table.out.partners[i].min_version;
420                 }
421                 if (strcmp(TEST_OWNER_B_ADDRESS,pull_table.out.partners[i].address)==0) {
422                         ctx->b.max_version      = pull_table.out.partners[i].max_version;
423                         ctx->b.min_version      = pull_table.out.partners[i].min_version;               
424                 }
425         }
426
427         talloc_free(pull_table.out.partners);
428
429         return ctx;
430 }
431
432 static BOOL test_wrepl_update_one(struct test_wrepl_conflict_conn *ctx,
433                                   const struct wrepl_wins_owner *owner,
434                                   const struct wrepl_wins_name *name)
435 {
436         BOOL ret = True;
437         struct wrepl_socket *wrepl_socket;
438         struct wrepl_associate associate;
439         struct wrepl_packet update_packet, repl_send;
440         struct wrepl_table *update;
441         struct wrepl_wins_owner wrepl_wins_owners[1];
442         struct wrepl_packet *repl_recv;
443         struct wrepl_wins_owner *send_request;
444         struct wrepl_send_reply *send_reply;
445         struct wrepl_wins_name wrepl_wins_names[1];
446         uint32_t assoc_ctx;
447         NTSTATUS status;
448
449         wrepl_socket = wrepl_socket_init(ctx, NULL);
450
451         status = wrepl_connect(wrepl_socket, NULL, ctx->address);
452         CHECK_STATUS(status, NT_STATUS_OK);
453
454         status = wrepl_associate(wrepl_socket, &associate);
455         CHECK_STATUS(status, NT_STATUS_OK);
456         assoc_ctx = associate.out.assoc_ctx;
457
458         /* now send a WREPL_REPL_UPDATE message */
459         ZERO_STRUCT(update_packet);
460         update_packet.opcode                    = WREPL_OPCODE_BITS;
461         update_packet.assoc_ctx                 = assoc_ctx;
462         update_packet.mess_type                 = WREPL_REPLICATION;
463         update_packet.message.replication.command       = WREPL_REPL_UPDATE;
464         update  = &update_packet.message.replication.info.table;
465
466         update->partner_count   = ARRAY_SIZE(wrepl_wins_owners);
467         update->partners        = wrepl_wins_owners;
468         update->initiator       = "0.0.0.0";
469
470         wrepl_wins_owners[0]    = *owner;
471
472         status = wrepl_request(wrepl_socket, wrepl_socket,
473                                &update_packet, &repl_recv);
474         CHECK_STATUS(status, NT_STATUS_OK);
475         CHECK_VALUE(repl_recv->mess_type, WREPL_REPLICATION);
476         CHECK_VALUE(repl_recv->message.replication.command, WREPL_REPL_SEND_REQUEST);
477         send_request = &repl_recv->message.replication.info.owner;
478
479         ZERO_STRUCT(repl_send);
480         repl_send.opcode                        = WREPL_OPCODE_BITS;
481         repl_send.assoc_ctx                     = assoc_ctx;
482         repl_send.mess_type                     = WREPL_REPLICATION;
483         repl_send.message.replication.command   = WREPL_REPL_SEND_REPLY;
484         send_reply = &repl_send.message.replication.info.reply;
485
486         send_reply->num_names   = ARRAY_SIZE(wrepl_wins_names);
487         send_reply->names       = wrepl_wins_names;
488
489         wrepl_wins_names[0]     = *name;
490
491         status = wrepl_request(wrepl_socket, wrepl_socket,
492                                &repl_send, &repl_recv);
493         CHECK_STATUS(status, NT_STATUS_OK);
494         CHECK_VALUE(repl_recv->mess_type, WREPL_STOP_ASSOCIATION);
495         CHECK_VALUE(repl_recv->message.stop.reason, 0);
496
497 done:
498         talloc_free(wrepl_socket);
499         return ret;
500 }
501
502 static BOOL test_wrepl_is_applied(struct test_wrepl_conflict_conn *ctx,
503                                   const struct wrepl_wins_owner *owner,
504                                   const struct wrepl_wins_name *name,
505                                   BOOL expected)
506 {
507         BOOL ret = True;
508         NTSTATUS status;
509         struct wrepl_pull_names pull_names;
510         struct wrepl_name *names;
511
512         pull_names.in.assoc_ctx = ctx->pull_assoc;
513         pull_names.in.partner   = *owner;
514         pull_names.in.partner.min_version = pull_names.in.partner.max_version;
515                 
516         status = wrepl_pull_names(ctx->pull, ctx->pull, &pull_names);
517         CHECK_STATUS(status, NT_STATUS_OK);
518         CHECK_VALUE(pull_names.out.num_names, (expected?1:0));
519
520         names = pull_names.out.names;
521
522         if (expected) {
523                 uint32_t flags = WREPL_NAME_FLAGS(names[0].type,
524                                                   names[0].state,
525                                                   names[0].node,
526                                                   names[0].is_static);
527                 CHECK_VALUE(names[0].name.type, name->name->type);
528                 CHECK_VALUE_STRING(names[0].name.name, name->name->name);
529                 CHECK_VALUE_STRING(names[0].name.scope, name->name->scope);
530                 CHECK_VALUE(flags, name->flags);
531                 CHECK_VALUE_UINT64(names[0].version_id, name->id);
532         }
533 done:
534         talloc_free(pull_names.out.names);
535         return ret;
536 }
537
538 static BOOL test_conflict_same_owner(struct test_wrepl_conflict_conn *ctx)
539 {
540         BOOL ret = True;
541         struct nbt_name name;
542         struct wrepl_wins_name wins_name1;
543         struct wrepl_wins_name wins_name2;
544         struct wrepl_wins_name *wins_name_tmp;
545         struct wrepl_wins_name *wins_name_last;
546         struct wrepl_wins_name *wins_name_cur;
547         uint32_t i,j;
548         uint8_t types[] = { 0x00, 0x1C };
549         struct {
550                 enum wrepl_name_type type;
551                 enum wrepl_name_state state;
552                 enum wrepl_name_node node;
553                 BOOL is_static;
554                 uint32_t num_ips;
555                 const struct wrepl_ip *ips;
556         } records[] = {
557                 {
558                 .type           = WREPL_TYPE_GROUP,
559                 .state          = WREPL_STATE_ACTIVE,
560                 .node           = WREPL_NODE_B,
561                 .is_static      = False,
562                 .num_ips        = ARRAY_SIZE(addresses_A_1),
563                 .ips            = addresses_A_1,
564                 },{
565                 .type           = WREPL_TYPE_UNIQUE,
566                 .state          = WREPL_STATE_ACTIVE,
567                 .node           = WREPL_NODE_B,
568                 .is_static      = False,
569                 .num_ips        = ARRAY_SIZE(addresses_A_1),
570                 .ips            = addresses_A_1,
571                 },{
572                 .type           = WREPL_TYPE_UNIQUE,
573                 .state          = WREPL_STATE_ACTIVE,
574                 .node           = WREPL_NODE_B,
575                 .is_static      = False,
576                 .num_ips        = ARRAY_SIZE(addresses_A_2),
577                 .ips            = addresses_A_2,
578                 },{
579                 .type           = WREPL_TYPE_UNIQUE,
580                 .state          = WREPL_STATE_ACTIVE,
581                 .node           = WREPL_NODE_B,
582                 .is_static      = True,
583                 .num_ips        = ARRAY_SIZE(addresses_A_1),
584                 .ips            = addresses_A_1,
585                 },{
586                 .type           = WREPL_TYPE_UNIQUE,
587                 .state          = WREPL_STATE_ACTIVE,
588                 .node           = WREPL_NODE_B,
589                 .is_static      = False,
590                 .num_ips        = ARRAY_SIZE(addresses_A_2),
591                 .ips            = addresses_A_2,
592                 },{
593                 .type           = WREPL_TYPE_SGROUP,
594                 .state          = WREPL_STATE_TOMBSTONE,
595                 .node           = WREPL_NODE_B,
596                 .is_static      = False,
597                 .num_ips        = ARRAY_SIZE(addresses_A_2),
598                 .ips            = addresses_A_2,
599                 },{
600                 .type           = WREPL_TYPE_MHOMED,
601                 .state          = WREPL_STATE_TOMBSTONE,
602                 .node           = WREPL_NODE_B,
603                 .is_static      = False,
604                 .num_ips        = ARRAY_SIZE(addresses_A_1),
605                 .ips            = addresses_A_1,
606                 },{
607                 .type           = WREPL_TYPE_MHOMED,
608                 .state          = WREPL_STATE_RELEASED,
609                 .node           = WREPL_NODE_B,
610                 .is_static      = False,
611                 .num_ips        = ARRAY_SIZE(addresses_A_2),
612                 .ips            = addresses_A_2,
613                 },{
614                 .type           = WREPL_TYPE_SGROUP,
615                 .state          = WREPL_STATE_ACTIVE,
616                 .node           = WREPL_NODE_B,
617                 .is_static      = False,
618                 .num_ips        = ARRAY_SIZE(addresses_A_1),
619                 .ips            = addresses_A_1,
620                 },{
621                 /* the last one should always be a unique,tomstone record! */
622                 .type           = WREPL_TYPE_UNIQUE,
623                 .state          = WREPL_STATE_TOMBSTONE,
624                 .node           = WREPL_NODE_B,
625                 .is_static      = False,
626                 .num_ips        = ARRAY_SIZE(addresses_A_1),
627                 .ips            = addresses_A_1,
628                 }
629         };
630
631         if (!ctx) return False;
632
633         name.name       = "_SAME_OWNER_A";
634         name.type       = 0;
635         name.scope      = NULL;
636
637         wins_name_tmp   = NULL;
638         wins_name_last  = &wins_name2;
639         wins_name_cur   = &wins_name1;
640
641         for (j=0; ret && j < ARRAY_SIZE(types); j++) {
642                 name.type = types[j];
643                 printf("Test Replica Conflicts with same owner[%s] for %s\n",
644                         nbt_name_string(ctx, &name), ctx->a.address);
645
646                 for(i=0; ret && i < ARRAY_SIZE(records); i++) {
647                         wins_name_tmp   = wins_name_last;
648                         wins_name_last  = wins_name_cur;
649                         wins_name_cur   = wins_name_tmp;
650
651                         if (i > 0) {
652                                 printf("%s,%s%s vs. %s,%s%s with %s ip(s) => %s\n",
653                                         wrepl_name_type_string(records[i-1].type),
654                                         wrepl_name_state_string(records[i-1].state),
655                                         (records[i-1].is_static?",static":""),
656                                         wrepl_name_type_string(records[i].type),
657                                         wrepl_name_state_string(records[i].state),
658                                         (records[i].is_static?",static":""),
659                                         (records[i-1].ips==records[i].ips?"same":"different"),
660                                         "REPLACE");
661                         }
662
663                         wins_name_cur->name     = &name;
664                         wins_name_cur->flags    = WREPL_NAME_FLAGS(records[i].type,
665                                                                    records[i].state,
666                                                                    records[i].node,
667                                                                    records[i].is_static);
668                         wins_name_cur->id       = ++ctx->a.max_version;
669                         if (wins_name_cur->flags & 2) {
670                                 wins_name_cur->addresses.addresses.num_ips = records[i].num_ips;
671                                 wins_name_cur->addresses.addresses.ips     = discard_const(records[i].ips);
672                         } else {
673                                 wins_name_cur->addresses.ip = records[i].ips[0].ip;
674                         }
675                         wins_name_cur->unknown  = "255.255.255.255";
676
677                         ret &= test_wrepl_update_one(ctx, &ctx->a,wins_name_cur);
678                         if (records[i].state == WREPL_STATE_RELEASED) {
679                                 ret &= test_wrepl_is_applied(ctx, &ctx->a, wins_name_last, False);
680                                 ret &= test_wrepl_is_applied(ctx, &ctx->a, wins_name_cur, False);
681                         } else {
682                                 ret &= test_wrepl_is_applied(ctx, &ctx->a, wins_name_cur, True);
683                         }
684
685                         /* the first one is a cleanup run */
686                         if (!ret && i == 0) ret = True;
687
688                         if (!ret) {
689                                 printf("conflict handled wrong or record[%u]: %s\n", i, __location__);
690                                 return ret;
691                         }
692                 }
693         }
694         return ret;
695 }
696
697 static BOOL test_conflict_different_owner(struct test_wrepl_conflict_conn *ctx)
698 {
699         BOOL ret = True;
700         struct wrepl_wins_name wins_name1;
701         struct wrepl_wins_name wins_name2;
702         struct wrepl_wins_name *wins_name_r1;
703         struct wrepl_wins_name *wins_name_r2;
704         uint32_t i;
705         struct {
706                 const char *line; /* just better debugging */
707                 struct nbt_name name;
708                 BOOL extra; /* not the worst case, this is an extra test */
709                 BOOL cleanup;
710                 struct {
711                         struct wrepl_wins_owner *owner;
712                         enum wrepl_name_type type;
713                         enum wrepl_name_state state;
714                         enum wrepl_name_node node;
715                         BOOL is_static;
716                         uint32_t num_ips;
717                         const struct wrepl_ip *ips;
718                         BOOL apply_expected;
719                 } r1, r2;
720         } records[] = {
721         /* 
722          * NOTE: the first record and the last applied one
723          *       needs to be from the same owner,
724          *       to not conflict in the next smbtorture run!!!
725          */
726         {
727                 .line   = __location__,
728                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
729                 .cleanup= True,
730                 .r1     = {
731                         .owner          = &ctx->b,
732                         .type           = WREPL_TYPE_UNIQUE,
733                         .state          = WREPL_STATE_TOMBSTONE,
734                         .node           = WREPL_NODE_B,
735                         .is_static      = False,
736                         .num_ips        = ARRAY_SIZE(addresses_B_1),
737                         .ips            = addresses_B_1,
738                         .apply_expected = True /* ignored */
739                 },
740                 .r2     = {
741                         .owner          = &ctx->a,
742                         .type           = WREPL_TYPE_UNIQUE,
743                         .state          = WREPL_STATE_TOMBSTONE,
744                         .node           = WREPL_NODE_B,
745                         .is_static      = False,
746                         .num_ips        = ARRAY_SIZE(addresses_A_1),
747                         .ips            = addresses_A_1,
748                         .apply_expected = True /* ignored */
749                 }
750         },
751
752 /*
753  * unique vs unique section
754  */
755         /* 
756          * unique,active vs. unique,active the same ip
757          * => should be replaced
758          */
759         {
760                 .line   = __location__,
761                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
762                 .extra  = True,
763                 .r1     = {
764                         .owner          = &ctx->a,
765                         .type           = WREPL_TYPE_UNIQUE,
766                         .state          = WREPL_STATE_ACTIVE,
767                         .node           = WREPL_NODE_B,
768                         .is_static      = False,
769                         .num_ips        = ARRAY_SIZE(addresses_A_1),
770                         .ips            = addresses_A_1,
771                         .apply_expected = True
772                 },
773                 .r2     = {
774                         .owner          = &ctx->b,
775                         .type           = WREPL_TYPE_UNIQUE,
776                         .state          = WREPL_STATE_ACTIVE,
777                         .node           = WREPL_NODE_B,
778                         .is_static      = False,
779                         .num_ips        = ARRAY_SIZE(addresses_A_1),
780                         .ips            = addresses_A_1,
781                         .apply_expected = True
782                 }
783         },
784
785         /* 
786          * unique,active vs. unique,tombstone the same ips
787          * => should NOT be replaced
788          */
789         {
790                 .line   = __location__,
791                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
792                 .extra  = True,
793                 .r1     = {
794                         .owner          = &ctx->b,
795                         .type           = WREPL_TYPE_UNIQUE,
796                         .state          = WREPL_STATE_ACTIVE,
797                         .node           = WREPL_NODE_B,
798                         .is_static      = False,
799                         .num_ips        = ARRAY_SIZE(addresses_B_1),
800                         .ips            = addresses_B_1,
801                         .apply_expected = True
802                 },
803                 .r2     = {
804                         .owner          = &ctx->a,
805                         .type           = WREPL_TYPE_UNIQUE,
806                         .state          = WREPL_STATE_TOMBSTONE,
807                         .node           = WREPL_NODE_B,
808                         .is_static      = False,
809                         .num_ips        = ARRAY_SIZE(addresses_B_1),
810                         .ips            = addresses_B_1,
811                         .apply_expected = False
812                 }
813         },
814
815         /* 
816          * unique,tombstone vs. unique,active the same ips
817          * => should NOT be replaced
818          */
819         {
820                 .line   = __location__,
821                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
822                 .extra  = True,
823                 .r1     = {
824                         .owner          = &ctx->b,
825                         .type           = WREPL_TYPE_UNIQUE,
826                         .state          = WREPL_STATE_TOMBSTONE,
827                         .node           = WREPL_NODE_B,
828                         .is_static      = False,
829                         .num_ips        = ARRAY_SIZE(addresses_B_1),
830                         .ips            = addresses_B_1,
831                         .apply_expected = True
832                 },
833                 .r2     = {
834                         .owner          = &ctx->a,
835                         .type           = WREPL_TYPE_UNIQUE,
836                         .state          = WREPL_STATE_ACTIVE,
837                         .node           = WREPL_NODE_B,
838                         .is_static      = False,
839                         .num_ips        = ARRAY_SIZE(addresses_B_1),
840                         .ips            = addresses_B_1,
841                         .apply_expected = True
842                 }
843         },
844
845         /* 
846          * unique,tombstone vs. unique,tombstone the same ips
847          * => should be replaced
848          */
849         {
850                 .line   = __location__,
851                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
852                 .extra  = True,
853                 .r1     = {
854                         .owner          = &ctx->a,
855                         .type           = WREPL_TYPE_UNIQUE,
856                         .state          = WREPL_STATE_TOMBSTONE,
857                         .node           = WREPL_NODE_B,
858                         .is_static      = False,
859                         .num_ips        = ARRAY_SIZE(addresses_A_1),
860                         .ips            = addresses_A_1,
861                         .apply_expected = True
862                 },
863                 .r2     = {
864                         .owner          = &ctx->b,
865                         .type           = WREPL_TYPE_UNIQUE,
866                         .state          = WREPL_STATE_TOMBSTONE,
867                         .node           = WREPL_NODE_B,
868                         .is_static      = False,
869                         .num_ips        = ARRAY_SIZE(addresses_A_1),
870                         .ips            = addresses_A_1,
871                         .apply_expected = True
872                 }
873         },
874
875         /* 
876          * unique,active vs. unique,active the different ips
877          * => should be replaced
878          */
879         {
880                 .line   = __location__,
881                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
882                 .r1     = {
883                         .owner          = &ctx->a,
884                         .type           = WREPL_TYPE_UNIQUE,
885                         .state          = WREPL_STATE_ACTIVE,
886                         .node           = WREPL_NODE_B,
887                         .is_static      = False,
888                         .num_ips        = ARRAY_SIZE(addresses_A_1),
889                         .ips            = addresses_A_1,
890                         .apply_expected = True
891                 },
892                 .r2     = {
893                         .owner          = &ctx->b,
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,active vs. unique,tombstone the different ips
906          * => should NOT be replaced
907          */
908         {
909                 .line   = __location__,
910                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
911                 .extra  = True,
912                 .r1     = {
913                         .owner          = &ctx->b,
914                         .type           = WREPL_TYPE_UNIQUE,
915                         .state          = WREPL_STATE_ACTIVE,
916                         .node           = WREPL_NODE_B,
917                         .is_static      = False,
918                         .num_ips        = ARRAY_SIZE(addresses_B_1),
919                         .ips            = addresses_B_1,
920                         .apply_expected = True
921                 },
922                 .r2     = {
923                         .owner          = &ctx->a,
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 = False
931                 }
932         },
933
934         /* 
935          * unique,tombstone 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->b,
943                         .type           = WREPL_TYPE_UNIQUE,
944                         .state          = WREPL_STATE_TOMBSTONE,
945                         .node           = WREPL_NODE_B,
946                         .is_static      = False,
947                         .num_ips        = ARRAY_SIZE(addresses_B_1),
948                         .ips            = addresses_B_1,
949                         .apply_expected = True
950                 },
951                 .r2     = {
952                         .owner          = &ctx->a,
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_A_1),
958                         .ips            = addresses_A_1,
959                         .apply_expected = True
960                 }
961         },
962
963         /* 
964          * unique,tombstone vs. unique,tombstone the different ips
965          * => should be replaced
966          */
967         {
968                 .line   = __location__,
969                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
970                 .r1     = {
971                         .owner          = &ctx->a,
972                         .type           = WREPL_TYPE_UNIQUE,
973                         .state          = WREPL_STATE_TOMBSTONE,
974                         .node           = WREPL_NODE_B,
975                         .is_static      = False,
976                         .num_ips        = ARRAY_SIZE(addresses_A_1),
977                         .ips            = addresses_A_1,
978                         .apply_expected = True
979                 },
980                 .r2     = {
981                         .owner          = &ctx->b,
982                         .type           = WREPL_TYPE_UNIQUE,
983                         .state          = WREPL_STATE_TOMBSTONE,
984                         .node           = WREPL_NODE_B,
985                         .is_static      = False,
986                         .num_ips        = ARRAY_SIZE(addresses_B_1),
987                         .ips            = addresses_B_1,
988                         .apply_expected = True
989                 }
990         },
991
992 /*
993  * unique vs normal groups section,
994  */
995         /* 
996          * unique,active vs. group,active
997          * => should be replaced
998          */
999         {
1000                 .line   = __location__,
1001                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1002                 .r1     = {
1003                         .owner          = &ctx->b,
1004                         .type           = WREPL_TYPE_UNIQUE,
1005                         .state          = WREPL_STATE_ACTIVE,
1006                         .node           = WREPL_NODE_B,
1007                         .is_static      = False,
1008                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1009                         .ips            = addresses_B_1,
1010                         .apply_expected = True
1011                 },
1012                 .r2     = {
1013                         .owner          = &ctx->a,
1014                         .type           = WREPL_TYPE_GROUP,
1015                         .state          = WREPL_STATE_ACTIVE,
1016                         .node           = WREPL_NODE_B,
1017                         .is_static      = False,
1018                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1019                         .ips            = addresses_A_1,
1020                         .apply_expected = True
1021                 }
1022         },
1023
1024         /* 
1025          * unique,active vs. group,tombstone same ip
1026          * => should NOT be replaced
1027          */
1028         {
1029                 .line   = __location__,
1030                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1031                 .r1     = {
1032                         .owner          = &ctx->a,
1033                         .type           = WREPL_TYPE_UNIQUE,
1034                         .state          = WREPL_STATE_ACTIVE,
1035                         .node           = WREPL_NODE_B,
1036                         .is_static      = False,
1037                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1038                         .ips            = addresses_A_1,
1039                         .apply_expected = True
1040                 },
1041                 .r2     = {
1042                         .owner          = &ctx->b,
1043                         .type           = WREPL_TYPE_GROUP,
1044                         .state          = WREPL_STATE_TOMBSTONE,
1045                         .node           = WREPL_NODE_B,
1046                         .is_static      = False,
1047                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1048                         .ips            = addresses_A_1,
1049                         .apply_expected = False
1050                 }
1051         },
1052
1053         /* 
1054          * unique,active vs. group,tombstone different ip
1055          * => should NOT be replaced
1056          */
1057         {
1058                 .line   = __location__,
1059                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1060                 .extra  = True,
1061                 .r1     = {
1062                         .owner          = &ctx->a,
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_A_1),
1068                         .ips            = addresses_A_1,
1069                         .apply_expected = True
1070                 },
1071                 .r2     = {
1072                         .owner          = &ctx->b,
1073                         .type           = WREPL_TYPE_GROUP,
1074                         .state          = WREPL_STATE_TOMBSTONE,
1075                         .node           = WREPL_NODE_B,
1076                         .is_static      = False,
1077                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1078                         .ips            = addresses_B_1,
1079                         .apply_expected = False
1080                 }
1081         },
1082
1083         /* 
1084          * unique,active vs. group,released
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_RELEASED,
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,tombstone vs. group,active
1114          * => should be replaced
1115          */
1116         {
1117                 .line   = __location__,
1118                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1119                 .r1     = {
1120                         .owner          = &ctx->a,
1121                         .type           = WREPL_TYPE_UNIQUE,
1122                         .state          = WREPL_STATE_TOMBSTONE,
1123                         .node           = WREPL_NODE_B,
1124                         .is_static      = False,
1125                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1126                         .ips            = addresses_A_1,
1127                         .apply_expected = True
1128                 },
1129                 .r2     = {
1130                         .owner          = &ctx->b,
1131                         .type           = WREPL_TYPE_GROUP,
1132                         .state          = WREPL_STATE_ACTIVE,
1133                         .node           = WREPL_NODE_B,
1134                         .is_static      = False,
1135                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1136                         .ips            = addresses_B_1,
1137                         .apply_expected = True
1138                 }
1139         },
1140
1141         /* 
1142          * unique,tombstone vs. group,tombstone
1143          * => should be replaced
1144          */
1145         {
1146                 .line   = __location__,
1147                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1148                 .r1     = {
1149                         .owner          = &ctx->b,
1150                         .type           = WREPL_TYPE_UNIQUE,
1151                         .state          = WREPL_STATE_TOMBSTONE,
1152                         .node           = WREPL_NODE_B,
1153                         .is_static      = False,
1154                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1155                         .ips            = addresses_B_1,
1156                         .apply_expected = True
1157                 },
1158                 .r2     = {
1159                         .owner          = &ctx->a,
1160                         .type           = WREPL_TYPE_GROUP,
1161                         .state          = WREPL_STATE_TOMBSTONE,
1162                         .node           = WREPL_NODE_B,
1163                         .is_static      = False,
1164                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1165                         .ips            = addresses_A_1,
1166                         .apply_expected = True
1167                 }
1168         },
1169
1170         /* 
1171          * unique,tombstone vs. group,released
1172          * => should be replaced
1173          */
1174         {
1175                 .line   = __location__,
1176                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1177                 .r1     = {
1178                         .owner          = &ctx->a,
1179                         .type           = WREPL_TYPE_UNIQUE,
1180                         .state          = WREPL_STATE_TOMBSTONE,
1181                         .node           = WREPL_NODE_B,
1182                         .is_static      = False,
1183                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1184                         .ips            = addresses_A_1,
1185                         .apply_expected = True
1186                 },
1187                 .r2     = {
1188                         .owner          = &ctx->b,
1189                         .type           = WREPL_TYPE_GROUP,
1190                         .state          = WREPL_STATE_RELEASED,
1191                         .node           = WREPL_NODE_B,
1192                         .is_static      = False,
1193                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1194                         .ips            = addresses_B_1,
1195                         .apply_expected = True
1196                 }
1197         },
1198
1199         /* 
1200          * unique,released vs. group,released
1201          * => should be replaced
1202          *
1203          * here we need a 2nd round to make sure
1204          * released vs. released is handled correct
1205          */
1206         {
1207                 .line   = __location__,
1208                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1209                 .r1     = {
1210                         .owner          = &ctx->b,
1211                         .type           = WREPL_TYPE_UNIQUE,
1212                         .state          = WREPL_STATE_RELEASED,
1213                         .node           = WREPL_NODE_B,
1214                         .is_static      = False,
1215                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1216                         .ips            = addresses_B_1,
1217                         .apply_expected = False
1218                 },
1219                 .r2     = {
1220                         .owner          = &ctx->a,
1221                         .type           = WREPL_TYPE_GROUP,
1222                         .state          = WREPL_STATE_RELEASED,
1223                         .node           = WREPL_NODE_B,
1224                         .is_static      = False,
1225                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1226                         .ips            = addresses_A_1,
1227                         .apply_expected = True
1228                 }
1229         },
1230         {
1231                 .line   = __location__,
1232                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1233                 .cleanup= True,
1234                 .r1     = {
1235                         .owner          = &ctx->b,
1236                         .type           = WREPL_TYPE_UNIQUE,
1237                         .state          = WREPL_STATE_TOMBSTONE,
1238                         .node           = WREPL_NODE_B,
1239                         .is_static      = False,
1240                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1241                         .ips            = addresses_A_1,
1242                         .apply_expected = False /* this should conflict with the group.released above */
1243                 },
1244                 .r2     = {
1245                         .owner          = &ctx->a,
1246                         .type           = WREPL_TYPE_GROUP,
1247                         .state          = WREPL_STATE_TOMBSTONE,
1248                         .node           = WREPL_NODE_B,
1249                         .is_static      = False,
1250                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1251                         .ips            = addresses_A_1,
1252                         .apply_expected = True
1253                 }
1254         },
1255
1256 /*
1257  * unique vs special groups section,
1258  */
1259         /* 
1260          * unique,active vs. sgroup,active
1261          * => should NOT be replaced
1262          */
1263         {
1264                 .line   = __location__,
1265                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1266                 .r1     = {
1267                         .owner          = &ctx->a,
1268                         .type           = WREPL_TYPE_UNIQUE,
1269                         .state          = WREPL_STATE_ACTIVE,
1270                         .node           = WREPL_NODE_B,
1271                         .is_static      = False,
1272                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1273                         .ips            = addresses_A_1,
1274                         .apply_expected = True
1275                 },
1276                 .r2     = {
1277                         .owner          = &ctx->b,
1278                         .type           = WREPL_TYPE_SGROUP,
1279                         .state          = WREPL_STATE_ACTIVE,
1280                         .node           = WREPL_NODE_B,
1281                         .is_static      = False,
1282                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1283                         .ips            = addresses_A_1,
1284                         .apply_expected = False
1285                 }
1286         },
1287
1288         /* 
1289          * unique,active vs. sgroup,tombstone
1290          * => should NOT be replaced
1291          */
1292         {
1293                 .line   = __location__,
1294                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1295                 .r1     = {
1296                         .owner          = &ctx->a,
1297                         .type           = WREPL_TYPE_UNIQUE,
1298                         .state          = WREPL_STATE_ACTIVE,
1299                         .node           = WREPL_NODE_B,
1300                         .is_static      = False,
1301                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1302                         .ips            = addresses_A_1,
1303                         .apply_expected = True
1304                 },
1305                 .r2     = {
1306                         .owner          = &ctx->b,
1307                         .type           = WREPL_TYPE_SGROUP,
1308                         .state          = WREPL_STATE_TOMBSTONE,
1309                         .node           = WREPL_NODE_B,
1310                         .is_static      = False,
1311                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1312                         .ips            = addresses_A_1,
1313                         .apply_expected = False
1314                 }
1315         },
1316
1317         /* 
1318          * unique,tombstone vs. sgroup,active
1319          * => should be replaced
1320          */
1321         {
1322                 .line   = __location__,
1323                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1324                 .r1     = {
1325                         .owner          = &ctx->a,
1326                         .type           = WREPL_TYPE_UNIQUE,
1327                         .state          = WREPL_STATE_TOMBSTONE,
1328                         .node           = WREPL_NODE_B,
1329                         .is_static      = False,
1330                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1331                         .ips            = addresses_A_1,
1332                         .apply_expected = True
1333                 },
1334                 .r2     = {
1335                         .owner          = &ctx->b,
1336                         .type           = WREPL_TYPE_SGROUP,
1337                         .state          = WREPL_STATE_ACTIVE,
1338                         .node           = WREPL_NODE_B,
1339                         .is_static      = False,
1340                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1341                         .ips            = addresses_B_3_4,
1342                         .apply_expected = True
1343                 }
1344         },
1345
1346         /* 
1347          * unique,tombstone vs. sgroup,tombstone
1348          * => should be replaced
1349          */
1350         {
1351                 .line   = __location__,
1352                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1353                 .r1     = {
1354                         .owner          = &ctx->b,
1355                         .type           = WREPL_TYPE_UNIQUE,
1356                         .state          = WREPL_STATE_TOMBSTONE,
1357                         .node           = WREPL_NODE_B,
1358                         .is_static      = False,
1359                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1360                         .ips            = addresses_B_1,
1361                         .apply_expected = True
1362                 },
1363                 .r2     = {
1364                         .owner          = &ctx->a,
1365                         .type           = WREPL_TYPE_SGROUP,
1366                         .state          = WREPL_STATE_TOMBSTONE,
1367                         .node           = WREPL_NODE_B,
1368                         .is_static      = False,
1369                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1370                         .ips            = addresses_A_3_4,
1371                         .apply_expected = True
1372                 }
1373         },
1374
1375
1376 /*
1377  * unique vs multi homed section,
1378  */
1379         /* 
1380          * unique,active vs. mhomed,active with different ips
1381          * => should be replaced
1382          */
1383         {
1384                 .line   = __location__,
1385                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1386                 .r1     = {
1387                         .owner          = &ctx->a,
1388                         .type           = WREPL_TYPE_UNIQUE,
1389                         .state          = WREPL_STATE_ACTIVE,
1390                         .node           = WREPL_NODE_B,
1391                         .is_static      = False,
1392                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1393                         .ips            = addresses_A_1,
1394                         .apply_expected = True
1395                 },
1396                 .r2     = {
1397                         .owner          = &ctx->b,
1398                         .type           = WREPL_TYPE_MHOMED,
1399                         .state          = WREPL_STATE_ACTIVE,
1400                         .node           = WREPL_NODE_B,
1401                         .is_static      = False,
1402                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1403                         .ips            = addresses_B_3_4,
1404                         .apply_expected = True
1405                 }
1406         },
1407
1408         /* 
1409          * unique,active vs. mhomed,tombstone with different ips
1410          * => should NOT be replaced
1411          */
1412         {
1413                 .line   = __location__,
1414                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1415                 .extra  = True,
1416                 .r1     = {
1417                         .owner          = &ctx->b,
1418                         .type           = WREPL_TYPE_UNIQUE,
1419                         .state          = WREPL_STATE_ACTIVE,
1420                         .node           = WREPL_NODE_B,
1421                         .is_static      = False,
1422                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1423                         .ips            = addresses_B_1,
1424                         .apply_expected = True
1425                 },
1426                 .r2     = {
1427                         .owner          = &ctx->a,
1428                         .type           = WREPL_TYPE_MHOMED,
1429                         .state          = WREPL_STATE_TOMBSTONE,
1430                         .node           = WREPL_NODE_B,
1431                         .is_static      = False,
1432                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1433                         .ips            = addresses_A_3_4,
1434                         .apply_expected = False
1435                 }
1436         },
1437
1438         /* 
1439          * unique,active vs. mhomed,tombstone with same ips
1440          * => should NOT be replaced
1441          */
1442         {
1443                 .line   = __location__,
1444                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1445                 .r1     = {
1446                         .owner          = &ctx->b,
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_B_3_4),
1452                         .ips            = addresses_B_3_4,
1453                         .apply_expected = True
1454                 },
1455                 .r2     = {
1456                         .owner          = &ctx->a,
1457                         .type           = WREPL_TYPE_MHOMED,
1458                         .state          = WREPL_STATE_TOMBSTONE,
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 = False
1464                 }
1465         },
1466
1467         /* 
1468          * unique,tombstone vs. mhomed,active with different ips
1469          * => should be replaced
1470          */
1471         {
1472                 .line   = __location__,
1473                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1474                 .r1     = {
1475                         .owner          = &ctx->b,
1476                         .type           = WREPL_TYPE_UNIQUE,
1477                         .state          = WREPL_STATE_TOMBSTONE,
1478                         .node           = WREPL_NODE_B,
1479                         .is_static      = False,
1480                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1481                         .ips            = addresses_B_1,
1482                         .apply_expected = True
1483                 },
1484                 .r2     = {
1485                         .owner          = &ctx->a,
1486                         .type           = WREPL_TYPE_MHOMED,
1487                         .state          = WREPL_STATE_ACTIVE,
1488                         .node           = WREPL_NODE_B,
1489                         .is_static      = False,
1490                         .num_ips        = ARRAY_SIZE(addresses_A_3_4),
1491                         .ips            = addresses_A_3_4,
1492                         .apply_expected = True
1493                 }
1494         },
1495
1496         /* 
1497          * unique,tombstone vs. mhomed,tombstone with different ips
1498          * => should be replaced
1499          */
1500         {
1501                 .line   = __location__,
1502                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1503                 .r1     = {
1504                         .owner          = &ctx->a,
1505                         .type           = WREPL_TYPE_UNIQUE,
1506                         .state          = WREPL_STATE_TOMBSTONE,
1507                         .node           = WREPL_NODE_B,
1508                         .is_static      = False,
1509                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1510                         .ips            = addresses_A_1,
1511                         .apply_expected = True
1512                 },
1513                 .r2     = {
1514                         .owner          = &ctx->b,
1515                         .type           = WREPL_TYPE_MHOMED,
1516                         .state          = WREPL_STATE_TOMBSTONE,
1517                         .node           = WREPL_NODE_B,
1518                         .is_static      = False,
1519                         .num_ips        = ARRAY_SIZE(addresses_B_3_4),
1520                         .ips            = addresses_B_3_4,
1521                         .apply_expected = True
1522                 }
1523         },
1524
1525 /*
1526  * normal groups vs unique section,
1527  */
1528         /* 
1529          * group,active vs. unique,active
1530          * => should NOT be replaced
1531          */
1532         {
1533                 .line   = __location__,
1534                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1535                 .r1     = {
1536                         .owner          = &ctx->a,
1537                         .type           = WREPL_TYPE_GROUP,
1538                         .state          = WREPL_STATE_ACTIVE,
1539                         .node           = WREPL_NODE_B,
1540                         .is_static      = False,
1541                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1542                         .ips            = addresses_A_1,
1543                         .apply_expected = True
1544                 },
1545                 .r2     = {
1546                         .owner          = &ctx->b,
1547                         .type           = WREPL_TYPE_UNIQUE,
1548                         .state          = WREPL_STATE_ACTIVE,
1549                         .node           = WREPL_NODE_B,
1550                         .is_static      = False,
1551                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1552                         .ips            = addresses_A_1,
1553                         .apply_expected = False
1554                 }
1555         },
1556
1557         /* 
1558          * group,active vs. unique,tombstone
1559          * => should NOT be replaced
1560          */
1561         {
1562                 .line   = __location__,
1563                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1564                 .r1     = {
1565                         .owner          = &ctx->a,
1566                         .type           = WREPL_TYPE_GROUP,
1567                         .state          = WREPL_STATE_ACTIVE,
1568                         .node           = WREPL_NODE_B,
1569                         .is_static      = False,
1570                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1571                         .ips            = addresses_A_1,
1572                         .apply_expected = True
1573                 },
1574                 .r2     = {
1575                         .owner          = &ctx->b,
1576                         .type           = WREPL_TYPE_UNIQUE,
1577                         .state          = WREPL_STATE_TOMBSTONE,
1578                         .node           = WREPL_NODE_B,
1579                         .is_static      = False,
1580                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1581                         .ips            = addresses_A_1,
1582                         .apply_expected = False
1583                 }
1584         },
1585
1586         /* 
1587          * group,released vs. unique,active
1588          * => should NOT be replaced
1589          */
1590         {
1591                 .line   = __location__,
1592                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1593                 .r1     = {
1594                         .owner          = &ctx->a,
1595                         .type           = WREPL_TYPE_GROUP,
1596                         .state          = WREPL_STATE_RELEASED,
1597                         .node           = WREPL_NODE_B,
1598                         .is_static      = False,
1599                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1600                         .ips            = addresses_A_1,
1601                         .apply_expected = False
1602                 },
1603                 .r2     = {
1604                         .owner          = &ctx->b,
1605                         .type           = WREPL_TYPE_UNIQUE,
1606                         .state          = WREPL_STATE_ACTIVE,
1607                         .node           = WREPL_NODE_B,
1608                         .is_static      = False,
1609                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1610                         .ips            = addresses_A_1,
1611                         .apply_expected = False
1612                 }
1613         },
1614
1615         /* 
1616          * group,released vs. unique,tombstone
1617          * => should NOT be replaced
1618          */
1619         {
1620                 .line   = __location__,
1621                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1622                 .r1     = {
1623                         .owner          = &ctx->a,
1624                         .type           = WREPL_TYPE_GROUP,
1625                         .state          = WREPL_STATE_RELEASED,
1626                         .node           = WREPL_NODE_B,
1627                         .is_static      = False,
1628                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1629                         .ips            = addresses_A_1,
1630                         .apply_expected = False
1631                 },
1632                 .r2     = {
1633                         .owner          = &ctx->b,
1634                         .type           = WREPL_TYPE_UNIQUE,
1635                         .state          = WREPL_STATE_TOMBSTONE,
1636                         .node           = WREPL_NODE_B,
1637                         .is_static      = False,
1638                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1639                         .ips            = addresses_A_1,
1640                         .apply_expected = False
1641                 }
1642         },
1643
1644         /* 
1645          * group,tombstone vs. unique,active
1646          * => should NOT be replaced
1647          */
1648         {
1649                 .line   = __location__,
1650                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1651                 .r1     = {
1652                         .owner          = &ctx->a,
1653                         .type           = WREPL_TYPE_GROUP,
1654                         .state          = WREPL_STATE_TOMBSTONE,
1655                         .node           = WREPL_NODE_B,
1656                         .is_static      = False,
1657                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1658                         .ips            = addresses_A_1,
1659                         .apply_expected = True
1660                 },
1661                 .r2     = {
1662                         .owner          = &ctx->b,
1663                         .type           = WREPL_TYPE_UNIQUE,
1664                         .state          = WREPL_STATE_ACTIVE,
1665                         .node           = WREPL_NODE_B,
1666                         .is_static      = False,
1667                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1668                         .ips            = addresses_A_1,
1669                         .apply_expected = False
1670                 }
1671         },
1672
1673         /* 
1674          * group,tombstone vs. unique,tombstone
1675          * => should NOT be replaced
1676          */
1677         {
1678                 .line   = __location__,
1679                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1680                 .r1     = {
1681                         .owner          = &ctx->a,
1682                         .type           = WREPL_TYPE_GROUP,
1683                         .state          = WREPL_STATE_TOMBSTONE,
1684                         .node           = WREPL_NODE_B,
1685                         .is_static      = False,
1686                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1687                         .ips            = addresses_A_1,
1688                         .apply_expected = True
1689                 },
1690                 .r2     = {
1691                         .owner          = &ctx->b,
1692                         .type           = WREPL_TYPE_UNIQUE,
1693                         .state          = WREPL_STATE_TOMBSTONE,
1694                         .node           = WREPL_NODE_B,
1695                         .is_static      = False,
1696                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1697                         .ips            = addresses_A_1,
1698                         .apply_expected = False
1699                 }
1700         },
1701
1702 /*
1703  * normal groups vs normal groups section,
1704  */
1705         /* 
1706          * group,active vs. group,active
1707          * => should NOT be replaced
1708          */
1709         {
1710                 .line   = __location__,
1711                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1712                 .r1     = {
1713                         .owner          = &ctx->a,
1714                         .type           = WREPL_TYPE_GROUP,
1715                         .state          = WREPL_STATE_ACTIVE,
1716                         .node           = WREPL_NODE_B,
1717                         .is_static      = False,
1718                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1719                         .ips            = addresses_A_1,
1720                         .apply_expected = True
1721                 },
1722                 .r2     = {
1723                         .owner          = &ctx->b,
1724                         .type           = WREPL_TYPE_GROUP,
1725                         .state          = WREPL_STATE_ACTIVE,
1726                         .node           = WREPL_NODE_B,
1727                         .is_static      = False,
1728                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1729                         .ips            = addresses_A_1,
1730                         .apply_expected = False
1731                 }
1732         },
1733
1734         /* 
1735          * group,active vs. group,tombstone
1736          * => should NOT be replaced
1737          */
1738         {
1739                 .line   = __location__,
1740                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1741                 .r1     = {
1742                         .owner          = &ctx->a,
1743                         .type           = WREPL_TYPE_GROUP,
1744                         .state          = WREPL_STATE_ACTIVE,
1745                         .node           = WREPL_NODE_B,
1746                         .is_static      = False,
1747                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1748                         .ips            = addresses_A_1,
1749                         .apply_expected = True
1750                 },
1751                 .r2     = {
1752                         .owner          = &ctx->b,
1753                         .type           = WREPL_TYPE_GROUP,
1754                         .state          = WREPL_STATE_TOMBSTONE,
1755                         .node           = WREPL_NODE_B,
1756                         .is_static      = False,
1757                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1758                         .ips            = addresses_A_1,
1759                         .apply_expected = False
1760                 }
1761         },
1762
1763         /* 
1764          * group,released vs. group,active
1765          * => should be replaced
1766          */
1767         {
1768                 .line   = __location__,
1769                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1770                 .r1     = {
1771                         .owner          = &ctx->a,
1772                         .type           = WREPL_TYPE_GROUP,
1773                         .state          = WREPL_STATE_RELEASED,
1774                         .node           = WREPL_NODE_B,
1775                         .is_static      = False,
1776                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1777                         .ips            = addresses_A_1,
1778                         .apply_expected = False
1779                 },
1780                 .r2     = {
1781                         .owner          = &ctx->b,
1782                         .type           = WREPL_TYPE_GROUP,
1783                         .state          = WREPL_STATE_ACTIVE,
1784                         .node           = WREPL_NODE_B,
1785                         .is_static      = False,
1786                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1787                         .ips            = addresses_B_1,
1788                         .apply_expected = True
1789                 }
1790         },
1791
1792         /* 
1793          * group,released vs. group,released
1794          * => should be replaced
1795          */
1796         {
1797                 .line   = __location__,
1798                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1799                 .r1     = {
1800                         .owner          = &ctx->b,
1801                         .type           = WREPL_TYPE_GROUP,
1802                         .state          = WREPL_STATE_RELEASED,
1803                         .node           = WREPL_NODE_B,
1804                         .is_static      = False,
1805                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1806                         .ips            = addresses_B_1,
1807                         .apply_expected = False
1808                 },
1809                 .r2     = {
1810                         .owner          = &ctx->a,
1811                         .type           = WREPL_TYPE_GROUP,
1812                         .state          = WREPL_STATE_RELEASED,
1813                         .node           = WREPL_NODE_B,
1814                         .is_static      = False,
1815                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1816                         .ips            = addresses_A_1,
1817                         .apply_expected = True
1818                 }
1819         },
1820         {
1821                 .line   = __location__,
1822                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1823                 .cleanup= True,
1824                 .r1     = {
1825                         .owner          = &ctx->b,
1826                         .type           = WREPL_TYPE_UNIQUE,
1827                         .state          = WREPL_STATE_TOMBSTONE,
1828                         .node           = WREPL_NODE_B,
1829                         .is_static      = False,
1830                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1831                         .ips            = addresses_B_1,
1832                         .apply_expected = False
1833                 },
1834                 .r2     = {
1835                         .owner          = &ctx->a,
1836                         .type           = WREPL_TYPE_UNIQUE,
1837                         .state          = WREPL_STATE_TOMBSTONE,
1838                         .node           = WREPL_NODE_B,
1839                         .is_static      = False,
1840                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1841                         .ips            = addresses_A_1,
1842                         .apply_expected = True
1843                 }
1844         },
1845
1846         /* 
1847          * group,released vs. group,tombstone
1848          * => should be replaced
1849          */
1850         {
1851                 .line   = __location__,
1852                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1853                 .r1     = {
1854                         .owner          = &ctx->a,
1855                         .type           = WREPL_TYPE_GROUP,
1856                         .state          = WREPL_STATE_RELEASED,
1857                         .node           = WREPL_NODE_B,
1858                         .is_static      = False,
1859                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1860                         .ips            = addresses_A_1,
1861                         .apply_expected = False
1862                 },
1863                 .r2     = {
1864                         .owner          = &ctx->b,
1865                         .type           = WREPL_TYPE_GROUP,
1866                         .state          = WREPL_STATE_TOMBSTONE,
1867                         .node           = WREPL_NODE_B,
1868                         .is_static      = False,
1869                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1870                         .ips            = addresses_B_1,
1871                         .apply_expected = True
1872                 }
1873         },
1874
1875         /* 
1876          * group,tombstone vs. group,active
1877          * => should be replaced
1878          */
1879         {
1880                 .line   = __location__,
1881                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1882                 .r1     = {
1883                         .owner          = &ctx->b,
1884                         .type           = WREPL_TYPE_GROUP,
1885                         .state          = WREPL_STATE_TOMBSTONE,
1886                         .node           = WREPL_NODE_B,
1887                         .is_static      = False,
1888                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1889                         .ips            = addresses_B_1,
1890                         .apply_expected = True
1891                 },
1892                 .r2     = {
1893                         .owner          = &ctx->a,
1894                         .type           = WREPL_TYPE_GROUP,
1895                         .state          = WREPL_STATE_ACTIVE,
1896                         .node           = WREPL_NODE_B,
1897                         .is_static      = False,
1898                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1899                         .ips            = addresses_A_1,
1900                         .apply_expected = True
1901                 }
1902         },
1903
1904         /* 
1905          * group,tombstone vs. group,tombstone
1906          * => should be replaced
1907          */
1908         {
1909                 .line   = __location__,
1910                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1911                 .r1     = {
1912                         .owner          = &ctx->a,
1913                         .type           = WREPL_TYPE_GROUP,
1914                         .state          = WREPL_STATE_TOMBSTONE,
1915                         .node           = WREPL_NODE_B,
1916                         .is_static      = False,
1917                         .num_ips        = ARRAY_SIZE(addresses_A_1),
1918                         .ips            = addresses_A_1,
1919                         .apply_expected = True
1920                 },
1921                 .r2     = {
1922                         .owner          = &ctx->b,
1923                         .type           = WREPL_TYPE_GROUP,
1924                         .state          = WREPL_STATE_TOMBSTONE,
1925                         .node           = WREPL_NODE_B,
1926                         .is_static      = False,
1927                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1928                         .ips            = addresses_B_1,
1929                         .apply_expected = True
1930                 }
1931         },
1932
1933 /*
1934  * normal groups vs special groups section,
1935  */
1936         /* 
1937          * group,active vs. sgroup,active
1938          * => should NOT be replaced
1939          */
1940         {
1941                 .line   = __location__,
1942                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1943                 .r1     = {
1944                         .owner          = &ctx->b,
1945                         .type           = WREPL_TYPE_GROUP,
1946                         .state          = WREPL_STATE_ACTIVE,
1947                         .node           = WREPL_NODE_B,
1948                         .is_static      = False,
1949                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1950                         .ips            = addresses_B_1,
1951                         .apply_expected = True
1952                 },
1953                 .r2     = {
1954                         .owner          = &ctx->a,
1955                         .type           = WREPL_TYPE_SGROUP,
1956                         .state          = WREPL_STATE_ACTIVE,
1957                         .node           = WREPL_NODE_B,
1958                         .is_static      = False,
1959                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1960                         .ips            = addresses_B_1,
1961                         .apply_expected = False
1962                 }
1963         },
1964
1965         /* 
1966          * group,active vs. sgroup,tombstone
1967          * => should NOT be replaced
1968          */
1969         {
1970                 .line   = __location__,
1971                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
1972                 .r1     = {
1973                         .owner          = &ctx->b,
1974                         .type           = WREPL_TYPE_GROUP,
1975                         .state          = WREPL_STATE_ACTIVE,
1976                         .node           = WREPL_NODE_B,
1977                         .is_static      = False,
1978                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1979                         .ips            = addresses_B_1,
1980                         .apply_expected = True
1981                 },
1982                 .r2     = {
1983                         .owner          = &ctx->a,
1984                         .type           = WREPL_TYPE_SGROUP,
1985                         .state          = WREPL_STATE_TOMBSTONE,
1986                         .node           = WREPL_NODE_B,
1987                         .is_static      = False,
1988                         .num_ips        = ARRAY_SIZE(addresses_B_1),
1989                         .ips            = addresses_B_1,
1990                         .apply_expected = False
1991                 }
1992         },
1993
1994         /* 
1995          * group,released vs. sgroup,active
1996          * => should be replaced
1997          */
1998         {
1999                 .line   = __location__,
2000                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2001                 .r1     = {
2002                         .owner          = &ctx->a,
2003                         .type           = WREPL_TYPE_GROUP,
2004                         .state          = WREPL_STATE_RELEASED,
2005                         .node           = WREPL_NODE_B,
2006                         .is_static      = False,
2007                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2008                         .ips            = addresses_A_1,
2009                         .apply_expected = False
2010                 },
2011                 .r2     = {
2012                         .owner          = &ctx->b,
2013                         .type           = WREPL_TYPE_SGROUP,
2014                         .state          = WREPL_STATE_ACTIVE,
2015                         .node           = WREPL_NODE_B,
2016                         .is_static      = False,
2017                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2018                         .ips            = addresses_B_1,
2019                         .apply_expected = True
2020                 }
2021         },
2022
2023         /* 
2024          * group,released vs. sgroup,released
2025          * => should NOT be replaced
2026          */
2027         {
2028                 .line   = __location__,
2029                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2030                 .r1     = {
2031                         .owner          = &ctx->b,
2032                         .type           = WREPL_TYPE_GROUP,
2033                         .state          = WREPL_STATE_RELEASED,
2034                         .node           = WREPL_NODE_B,
2035                         .is_static      = False,
2036                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2037                         .ips            = addresses_B_1,
2038                         .apply_expected = False
2039                 },
2040                 .r2     = {
2041                         .owner          = &ctx->a,
2042                         .type           = WREPL_TYPE_SGROUP,
2043                         .state          = WREPL_STATE_RELEASED,
2044                         .node           = WREPL_NODE_B,
2045                         .is_static      = False,
2046                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2047                         .ips            = addresses_B_1,
2048                         .apply_expected = False
2049                 }
2050         },
2051         {
2052                 .line   = __location__,
2053                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2054                 .cleanup= True,
2055                 .r1     = {
2056                         .owner          = &ctx->a,
2057                         .type           = WREPL_TYPE_UNIQUE,
2058                         .state          = WREPL_STATE_TOMBSTONE,
2059                         .node           = WREPL_NODE_B,
2060                         .is_static      = False,
2061                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2062                         .ips            = addresses_A_1,
2063                         .apply_expected = False
2064                 },
2065                 .r2     = {
2066                         .owner          = &ctx->b,
2067                         .type           = WREPL_TYPE_UNIQUE,
2068                         .state          = WREPL_STATE_TOMBSTONE,
2069                         .node           = WREPL_NODE_B,
2070                         .is_static      = False,
2071                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2072                         .ips            = addresses_B_1,
2073                         .apply_expected = True
2074                 }
2075         },
2076
2077         /* 
2078          * group,released vs. sgroup,tombstone
2079          * => should NOT be replaced
2080          */
2081         {
2082                 .line   = __location__,
2083                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2084                 .r1     = {
2085                         .owner          = &ctx->b,
2086                         .type           = WREPL_TYPE_GROUP,
2087                         .state          = WREPL_STATE_RELEASED,
2088                         .node           = WREPL_NODE_B,
2089                         .is_static      = False,
2090                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2091                         .ips            = addresses_B_1,
2092                         .apply_expected = False
2093                 },
2094                 .r2     = {
2095                         .owner          = &ctx->a,
2096                         .type           = WREPL_TYPE_SGROUP,
2097                         .state          = WREPL_STATE_TOMBSTONE,
2098                         .node           = WREPL_NODE_B,
2099                         .is_static      = False,
2100                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2101                         .ips            = addresses_B_1,
2102                         .apply_expected = False
2103                 }
2104         },
2105
2106         /* 
2107          * group,tombstone vs. sgroup,active
2108          * => should be replaced
2109          */
2110         {
2111                 .line   = __location__,
2112                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2113                 .r1     = {
2114                         .owner          = &ctx->b,
2115                         .type           = WREPL_TYPE_GROUP,
2116                         .state          = WREPL_STATE_TOMBSTONE,
2117                         .node           = WREPL_NODE_B,
2118                         .is_static      = False,
2119                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2120                         .ips            = addresses_B_1,
2121                         .apply_expected = True
2122                 },
2123                 .r2     = {
2124                         .owner          = &ctx->a,
2125                         .type           = WREPL_TYPE_SGROUP,
2126                         .state          = WREPL_STATE_ACTIVE,
2127                         .node           = WREPL_NODE_B,
2128                         .is_static      = False,
2129                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2130                         .ips            = addresses_A_1,
2131                         .apply_expected = True
2132                 }
2133         },
2134
2135         /* 
2136          * group,tombstone vs. sgroup,tombstone
2137          * => should be replaced
2138          */
2139         {
2140                 .line   = __location__,
2141                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2142                 .r1     = {
2143                         .owner          = &ctx->a,
2144                         .type           = WREPL_TYPE_GROUP,
2145                         .state          = WREPL_STATE_TOMBSTONE,
2146                         .node           = WREPL_NODE_B,
2147                         .is_static      = False,
2148                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2149                         .ips            = addresses_A_1,
2150                         .apply_expected = True
2151                 },
2152                 .r2     = {
2153                         .owner          = &ctx->b,
2154                         .type           = WREPL_TYPE_SGROUP,
2155                         .state          = WREPL_STATE_TOMBSTONE,
2156                         .node           = WREPL_NODE_B,
2157                         .is_static      = False,
2158                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2159                         .ips            = addresses_B_1,
2160                         .apply_expected = True
2161                 }
2162         },
2163
2164 /*
2165  * normal groups vs multi homed section,
2166  */
2167         /* 
2168          * group,active vs. mhomed,active
2169          * => should NOT be replaced
2170          */
2171         {
2172                 .line   = __location__,
2173                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2174                 .r1     = {
2175                         .owner          = &ctx->b,
2176                         .type           = WREPL_TYPE_GROUP,
2177                         .state          = WREPL_STATE_ACTIVE,
2178                         .node           = WREPL_NODE_B,
2179                         .is_static      = False,
2180                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2181                         .ips            = addresses_B_1,
2182                         .apply_expected = True
2183                 },
2184                 .r2     = {
2185                         .owner          = &ctx->a,
2186                         .type           = WREPL_TYPE_MHOMED,
2187                         .state          = WREPL_STATE_ACTIVE,
2188                         .node           = WREPL_NODE_B,
2189                         .is_static      = False,
2190                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2191                         .ips            = addresses_B_1,
2192                         .apply_expected = False
2193                 }
2194         },
2195
2196         /* 
2197          * group,active vs. mhomed,tombstone
2198          * => should NOT be replaced
2199          */
2200         {
2201                 .line   = __location__,
2202                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2203                 .r1     = {
2204                         .owner          = &ctx->b,
2205                         .type           = WREPL_TYPE_GROUP,
2206                         .state          = WREPL_STATE_ACTIVE,
2207                         .node           = WREPL_NODE_B,
2208                         .is_static      = False,
2209                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2210                         .ips            = addresses_B_1,
2211                         .apply_expected = True
2212                 },
2213                 .r2     = {
2214                         .owner          = &ctx->a,
2215                         .type           = WREPL_TYPE_MHOMED,
2216                         .state          = WREPL_STATE_TOMBSTONE,
2217                         .node           = WREPL_NODE_B,
2218                         .is_static      = False,
2219                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2220                         .ips            = addresses_B_1,
2221                         .apply_expected = False
2222                 }
2223         },
2224
2225         /* 
2226          * group,released vs. mhomed,active
2227          * => should NOT be replaced
2228          */
2229         {
2230                 .line   = __location__,
2231                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2232                 .r1     = {
2233                         .owner          = &ctx->b,
2234                         .type           = WREPL_TYPE_GROUP,
2235                         .state          = WREPL_STATE_RELEASED,
2236                         .node           = WREPL_NODE_B,
2237                         .is_static      = False,
2238                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2239                         .ips            = addresses_B_1,
2240                         .apply_expected = False
2241                 },
2242                 .r2     = {
2243                         .owner          = &ctx->a,
2244                         .type           = WREPL_TYPE_MHOMED,
2245                         .state          = WREPL_STATE_ACTIVE,
2246                         .node           = WREPL_NODE_B,
2247                         .is_static      = False,
2248                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2249                         .ips            = addresses_B_1,
2250                         .apply_expected = False
2251                 }
2252         },
2253
2254         /* 
2255          * group,released vs. mhomed,released
2256          * => should NOT be replaced
2257          */
2258         {
2259                 .line   = __location__,
2260                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2261                 .r1     = {
2262                         .owner          = &ctx->b,
2263                         .type           = WREPL_TYPE_GROUP,
2264                         .state          = WREPL_STATE_RELEASED,
2265                         .node           = WREPL_NODE_B,
2266                         .is_static      = False,
2267                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2268                         .ips            = addresses_B_1,
2269                         .apply_expected = False
2270                 },
2271                 .r2     = {
2272                         .owner          = &ctx->a,
2273                         .type           = WREPL_TYPE_MHOMED,
2274                         .state          = WREPL_STATE_RELEASED,
2275                         .node           = WREPL_NODE_B,
2276                         .is_static      = False,
2277                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2278                         .ips            = addresses_B_1,
2279                         .apply_expected = False
2280                 }
2281         },
2282         {
2283                 .line   = __location__,
2284                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2285                 .cleanup= True,
2286                 .r1     = {
2287                         .owner          = &ctx->a,
2288                         .type           = WREPL_TYPE_UNIQUE,
2289                         .state          = WREPL_STATE_TOMBSTONE,
2290                         .node           = WREPL_NODE_B,
2291                         .is_static      = False,
2292                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2293                         .ips            = addresses_A_1,
2294                         .apply_expected = False
2295                 },
2296                 .r2     = {
2297                         .owner          = &ctx->b,
2298                         .type           = WREPL_TYPE_UNIQUE,
2299                         .state          = WREPL_STATE_TOMBSTONE,
2300                         .node           = WREPL_NODE_B,
2301                         .is_static      = False,
2302                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2303                         .ips            = addresses_B_1,
2304                         .apply_expected = True
2305                 }
2306         },
2307
2308         /* 
2309          * group,released vs. mhomed,tombstone
2310          * => should NOT be replaced
2311          */
2312         {
2313                 .line   = __location__,
2314                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2315                 .r1     = {
2316                         .owner          = &ctx->b,
2317                         .type           = WREPL_TYPE_GROUP,
2318                         .state          = WREPL_STATE_RELEASED,
2319                         .node           = WREPL_NODE_B,
2320                         .is_static      = False,
2321                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2322                         .ips            = addresses_B_1,
2323                         .apply_expected = False
2324                 },
2325                 .r2     = {
2326                         .owner          = &ctx->a,
2327                         .type           = WREPL_TYPE_MHOMED,
2328                         .state          = WREPL_STATE_TOMBSTONE,
2329                         .node           = WREPL_NODE_B,
2330                         .is_static      = False,
2331                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2332                         .ips            = addresses_B_1,
2333                         .apply_expected = False
2334                 }
2335         },
2336
2337         /* 
2338          * group,tombstone vs. mhomed,active
2339          * => should be replaced
2340          */
2341         {
2342                 .line   = __location__,
2343                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2344                 .r1     = {
2345                         .owner          = &ctx->b,
2346                         .type           = WREPL_TYPE_GROUP,
2347                         .state          = WREPL_STATE_TOMBSTONE,
2348                         .node           = WREPL_NODE_B,
2349                         .is_static      = False,
2350                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2351                         .ips            = addresses_B_1,
2352                         .apply_expected = True
2353                 },
2354                 .r2     = {
2355                         .owner          = &ctx->a,
2356                         .type           = WREPL_TYPE_MHOMED,
2357                         .state          = WREPL_STATE_ACTIVE,
2358                         .node           = WREPL_NODE_B,
2359                         .is_static      = False,
2360                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2361                         .ips            = addresses_A_1,
2362                         .apply_expected = True
2363                 }
2364         },
2365
2366         /* 
2367          * group,tombstone vs. mhomed,tombstone
2368          * => should be replaced
2369          */
2370         {
2371                 .line   = __location__,
2372                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2373                 .r1     = {
2374                         .owner          = &ctx->a,
2375                         .type           = WREPL_TYPE_GROUP,
2376                         .state          = WREPL_STATE_TOMBSTONE,
2377                         .node           = WREPL_NODE_B,
2378                         .is_static      = False,
2379                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2380                         .ips            = addresses_A_1,
2381                         .apply_expected = True
2382                 },
2383                 .r2     = {
2384                         .owner          = &ctx->b,
2385                         .type           = WREPL_TYPE_MHOMED,
2386                         .state          = WREPL_STATE_TOMBSTONE,
2387                         .node           = WREPL_NODE_B,
2388                         .is_static      = False,
2389                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2390                         .ips            = addresses_B_1,
2391                         .apply_expected = True
2392                 }
2393         },
2394
2395 /*
2396  * special groups vs unique section,
2397  */
2398         /* 
2399          * sgroup,active vs. unique,active
2400          * => should NOT be replaced
2401          */
2402         {
2403                 .line   = __location__,
2404                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2405                 .r1     = {
2406                         .owner          = &ctx->b,
2407                         .type           = WREPL_TYPE_SGROUP,
2408                         .state          = WREPL_STATE_ACTIVE,
2409                         .node           = WREPL_NODE_B,
2410                         .is_static      = False,
2411                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2412                         .ips            = addresses_B_1,
2413                         .apply_expected = True
2414                 },
2415                 .r2     = {
2416                         .owner          = &ctx->a,
2417                         .type           = WREPL_TYPE_UNIQUE,
2418                         .state          = WREPL_STATE_ACTIVE,
2419                         .node           = WREPL_NODE_B,
2420                         .is_static      = False,
2421                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2422                         .ips            = addresses_B_1,
2423                         .apply_expected = False
2424                 }
2425         },
2426
2427         /* 
2428          * sgroup,active vs. unique,tombstone
2429          * => should NOT be replaced
2430          */
2431         {
2432                 .line   = __location__,
2433                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2434                 .r1     = {
2435                         .owner          = &ctx->b,
2436                         .type           = WREPL_TYPE_SGROUP,
2437                         .state          = WREPL_STATE_ACTIVE,
2438                         .node           = WREPL_NODE_B,
2439                         .is_static      = False,
2440                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2441                         .ips            = addresses_B_1,
2442                         .apply_expected = True
2443                 },
2444                 .r2     = {
2445                         .owner          = &ctx->a,
2446                         .type           = WREPL_TYPE_UNIQUE,
2447                         .state          = WREPL_STATE_TOMBSTONE,
2448                         .node           = WREPL_NODE_B,
2449                         .is_static      = False,
2450                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2451                         .ips            = addresses_B_1,
2452                         .apply_expected = False
2453                 }
2454         },
2455
2456         /* 
2457          * sgroup,released vs. unique,active
2458          * => should be replaced
2459          */
2460         {
2461                 .line   = __location__,
2462                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2463                 .r1     = {
2464                         .owner          = &ctx->b,
2465                         .type           = WREPL_TYPE_SGROUP,
2466                         .state          = WREPL_STATE_RELEASED,
2467                         .node           = WREPL_NODE_B,
2468                         .is_static      = False,
2469                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2470                         .ips            = addresses_B_1,
2471                         .apply_expected = False
2472                 },
2473                 .r2     = {
2474                         .owner          = &ctx->a,
2475                         .type           = WREPL_TYPE_UNIQUE,
2476                         .state          = WREPL_STATE_ACTIVE,
2477                         .node           = WREPL_NODE_B,
2478                         .is_static      = False,
2479                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2480                         .ips            = addresses_A_1,
2481                         .apply_expected = True
2482                 }
2483         },
2484
2485         /* 
2486          * sgroup,released vs. unique,tombstone
2487          * => should be replaced
2488          */
2489         {
2490                 .line   = __location__,
2491                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2492                 .r1     = {
2493                         .owner          = &ctx->a,
2494                         .type           = WREPL_TYPE_SGROUP,
2495                         .state          = WREPL_STATE_RELEASED,
2496                         .node           = WREPL_NODE_B,
2497                         .is_static      = False,
2498                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2499                         .ips            = addresses_A_1,
2500                         .apply_expected = False
2501                 },
2502                 .r2     = {
2503                         .owner          = &ctx->b,
2504                         .type           = WREPL_TYPE_UNIQUE,
2505                         .state          = WREPL_STATE_TOMBSTONE,
2506                         .node           = WREPL_NODE_B,
2507                         .is_static      = False,
2508                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2509                         .ips            = addresses_B_1,
2510                         .apply_expected = True
2511                 }
2512         },
2513
2514         /* 
2515          * sgroup,tombstone vs. unique,active
2516          * => should be replaced
2517          */
2518         {
2519                 .line   = __location__,
2520                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2521                 .r1     = {
2522                         .owner          = &ctx->a,
2523                         .type           = WREPL_TYPE_SGROUP,
2524                         .state          = WREPL_STATE_TOMBSTONE,
2525                         .node           = WREPL_NODE_B,
2526                         .is_static      = False,
2527                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2528                         .ips            = addresses_A_1,
2529                         .apply_expected = True
2530                 },
2531                 .r2     = {
2532                         .owner          = &ctx->b,
2533                         .type           = WREPL_TYPE_UNIQUE,
2534                         .state          = WREPL_STATE_ACTIVE,
2535                         .node           = WREPL_NODE_B,
2536                         .is_static      = False,
2537                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2538                         .ips            = addresses_B_1,
2539                         .apply_expected = True
2540                 }
2541         },
2542
2543         /* 
2544          * sgroup,tombstone vs. unique,tombstone
2545          * => should be replaced
2546          */
2547         {
2548                 .line   = __location__,
2549                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2550                 .r1     = {
2551                         .owner          = &ctx->b,
2552                         .type           = WREPL_TYPE_SGROUP,
2553                         .state          = WREPL_STATE_TOMBSTONE,
2554                         .node           = WREPL_NODE_B,
2555                         .is_static      = False,
2556                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2557                         .ips            = addresses_B_1,
2558                         .apply_expected = True
2559                 },
2560                 .r2     = {
2561                         .owner          = &ctx->a,
2562                         .type           = WREPL_TYPE_UNIQUE,
2563                         .state          = WREPL_STATE_TOMBSTONE,
2564                         .node           = WREPL_NODE_B,
2565                         .is_static      = False,
2566                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2567                         .ips            = addresses_A_1,
2568                         .apply_expected = True
2569                 }
2570         },
2571
2572 /*
2573  * special groups vs normal group section,
2574  */
2575         /* 
2576          * sgroup,active vs. group,active
2577          * => should NOT be replaced
2578          */
2579         {
2580                 .line   = __location__,
2581                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2582                 .r1     = {
2583                         .owner          = &ctx->a,
2584                         .type           = WREPL_TYPE_SGROUP,
2585                         .state          = WREPL_STATE_ACTIVE,
2586                         .node           = WREPL_NODE_B,
2587                         .is_static      = False,
2588                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2589                         .ips            = addresses_A_1,
2590                         .apply_expected = True
2591                 },
2592                 .r2     = {
2593                         .owner          = &ctx->b,
2594                         .type           = WREPL_TYPE_GROUP,
2595                         .state          = WREPL_STATE_ACTIVE,
2596                         .node           = WREPL_NODE_B,
2597                         .is_static      = False,
2598                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2599                         .ips            = addresses_A_1,
2600                         .apply_expected = False
2601                 }
2602         },
2603
2604         /* 
2605          * sgroup,active vs. group,tombstone
2606          * => should NOT be replaced
2607          */
2608         {
2609                 .line   = __location__,
2610                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2611                 .r1     = {
2612                         .owner          = &ctx->a,
2613                         .type           = WREPL_TYPE_SGROUP,
2614                         .state          = WREPL_STATE_ACTIVE,
2615                         .node           = WREPL_NODE_B,
2616                         .is_static      = False,
2617                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2618                         .ips            = addresses_A_1,
2619                         .apply_expected = True
2620                 },
2621                 .r2     = {
2622                         .owner          = &ctx->b,
2623                         .type           = WREPL_TYPE_GROUP,
2624                         .state          = WREPL_STATE_TOMBSTONE,
2625                         .node           = WREPL_NODE_B,
2626                         .is_static      = False,
2627                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2628                         .ips            = addresses_A_1,
2629                         .apply_expected = False
2630                 }
2631         },
2632
2633         /* 
2634          * sgroup,released vs. group,active
2635          * => should be replaced
2636          */
2637         {
2638                 .line   = __location__,
2639                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2640                 .r1     = {
2641                         .owner          = &ctx->a,
2642                         .type           = WREPL_TYPE_SGROUP,
2643                         .state          = WREPL_STATE_RELEASED,
2644                         .node           = WREPL_NODE_B,
2645                         .is_static      = False,
2646                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2647                         .ips            = addresses_A_1,
2648                         .apply_expected = False
2649                 },
2650                 .r2     = {
2651                         .owner          = &ctx->b,
2652                         .type           = WREPL_TYPE_GROUP,
2653                         .state          = WREPL_STATE_ACTIVE,
2654                         .node           = WREPL_NODE_B,
2655                         .is_static      = False,
2656                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2657                         .ips            = addresses_B_1,
2658                         .apply_expected = True
2659                 }
2660         },
2661
2662         /* 
2663          * sgroup,released vs. group,tombstone
2664          * => should be replaced
2665          */
2666         {
2667                 .line   = __location__,
2668                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2669                 .r1     = {
2670                         .owner          = &ctx->b,
2671                         .type           = WREPL_TYPE_SGROUP,
2672                         .state          = WREPL_STATE_RELEASED,
2673                         .node           = WREPL_NODE_B,
2674                         .is_static      = False,
2675                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2676                         .ips            = addresses_B_1,
2677                         .apply_expected = False
2678                 },
2679                 .r2     = {
2680                         .owner          = &ctx->a,
2681                         .type           = WREPL_TYPE_GROUP,
2682                         .state          = WREPL_STATE_TOMBSTONE,
2683                         .node           = WREPL_NODE_B,
2684                         .is_static      = False,
2685                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2686                         .ips            = addresses_A_1,
2687                         .apply_expected = True
2688                 }
2689         },
2690
2691         /* 
2692          * sgroup,tombstone vs. group,active
2693          * => should NOT be replaced
2694          */
2695         {
2696                 .line   = __location__,
2697                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2698                 .r1     = {
2699                         .owner          = &ctx->a,
2700                         .type           = WREPL_TYPE_SGROUP,
2701                         .state          = WREPL_STATE_TOMBSTONE,
2702                         .node           = WREPL_NODE_B,
2703                         .is_static      = False,
2704                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2705                         .ips            = addresses_A_1,
2706                         .apply_expected = True
2707                 },
2708                 .r2     = {
2709                         .owner          = &ctx->b,
2710                         .type           = WREPL_TYPE_GROUP,
2711                         .state          = WREPL_STATE_ACTIVE,
2712                         .node           = WREPL_NODE_B,
2713                         .is_static      = False,
2714                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2715                         .ips            = addresses_B_1,
2716                         .apply_expected = True
2717                 }
2718         },
2719
2720         /* 
2721          * sgroup,tombstone vs. group,tombstone
2722          * => should NOT be replaced
2723          */
2724         {
2725                 .line   = __location__,
2726                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2727                 .r1     = {
2728                         .owner          = &ctx->b,
2729                         .type           = WREPL_TYPE_SGROUP,
2730                         .state          = WREPL_STATE_TOMBSTONE,
2731                         .node           = WREPL_NODE_B,
2732                         .is_static      = False,
2733                         .num_ips        = ARRAY_SIZE(addresses_B_1),
2734                         .ips            = addresses_B_1,
2735                         .apply_expected = True
2736                 },
2737                 .r2     = {
2738                         .owner          = &ctx->a,
2739                         .type           = WREPL_TYPE_GROUP,
2740                         .state          = WREPL_STATE_TOMBSTONE,
2741                         .node           = WREPL_NODE_B,
2742                         .is_static      = False,
2743                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2744                         .ips            = addresses_A_1,
2745                         .apply_expected = True
2746                 }
2747         },
2748
2749         /* 
2750          * This should be the last record in this array,
2751          * we need to make sure the we leave a tombstoned unique entry
2752          * owned by OWNER_A
2753          */
2754         {
2755                 .line   = __location__,
2756                 .name   = _NBT_NAME("_DIFF_OWNER", 0x00, NULL),
2757                 .cleanup= True,
2758                 .r1     = {
2759                         .owner          = &ctx->a,
2760                         .type           = WREPL_TYPE_UNIQUE,
2761                         .state          = WREPL_STATE_TOMBSTONE,
2762                         .node           = WREPL_NODE_B,
2763                         .is_static      = False,
2764                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2765                         .ips            = addresses_A_1,
2766                         .apply_expected = True
2767                 },
2768                 .r2     = {
2769                         .owner          = &ctx->a,
2770                         .type           = WREPL_TYPE_UNIQUE,
2771                         .state          = WREPL_STATE_TOMBSTONE,
2772                         .node           = WREPL_NODE_B,
2773                         .is_static      = False,
2774                         .num_ips        = ARRAY_SIZE(addresses_A_1),
2775                         .ips            = addresses_A_1,
2776                         .apply_expected = True
2777                 }
2778         }}; /* do not add entries here, this should be the last record! */
2779
2780         if (!ctx) return False;
2781
2782         wins_name_r1    = &wins_name1;
2783         wins_name_r2    = &wins_name2;
2784
2785         printf("Test Replica Conflicts with different owners\n");
2786
2787         for(i=0; ret && i < ARRAY_SIZE(records); i++) {
2788         
2789                 if (!records[i].extra && !records[i].cleanup) {
2790                         /* we should test the worst cases */
2791                         if (records[i].r2.apply_expected && records[i].r1.ips==records[i].r2.ips) {
2792                                 printf("(%s) Programmer error, invalid record[%u]: %s\n",
2793                                         __location__, i, records[i].line);
2794                                 return False;
2795                         } else if (!records[i].r2.apply_expected && records[i].r1.ips!=records[i].r2.ips) {
2796                                 printf("(%s) Programmer error, invalid record[%u]: %s\n",
2797                                         __location__, i, records[i].line);
2798                                 return False;
2799                         }
2800                 }
2801
2802                 if (!records[i].cleanup) {
2803                         printf("%s,%s%s vs. %s,%s%s with %s ip(s) => %s\n",
2804                                 wrepl_name_type_string(records[i].r1.type),
2805                                 wrepl_name_state_string(records[i].r1.state),
2806                                 (records[i].r1.is_static?",static":""),
2807                                 wrepl_name_type_string(records[i].r2.type),
2808                                 wrepl_name_state_string(records[i].r2.state),
2809                                 (records[i].r2.is_static?",static":""),
2810                                 (records[i].r1.ips==records[i].r2.ips?"same":"different"),
2811                                 (records[i].r2.apply_expected?"REPLACE":"NOT REPLACE"));
2812                 }
2813
2814                 /*
2815                  * Setup R1
2816                  */
2817                 wins_name_r1->name      = &records[i].name;
2818                 wins_name_r1->flags     = WREPL_NAME_FLAGS(records[i].r1.type,
2819                                                            records[i].r1.state,
2820                                                            records[i].r1.node,
2821                                                            records[i].r1.is_static);
2822                 wins_name_r1->id        = ++records[i].r1.owner->max_version;
2823                 if (wins_name_r1->flags & 2) {
2824                         wins_name_r1->addresses.addresses.num_ips = records[i].r1.num_ips;
2825                         wins_name_r1->addresses.addresses.ips     = discard_const(records[i].r1.ips);
2826                 } else {
2827                         wins_name_r1->addresses.ip = records[i].r1.ips[0].ip;
2828                 }
2829                 wins_name_r1->unknown   = "255.255.255.255";
2830
2831                 /* now apply R1 */
2832                 ret &= test_wrepl_update_one(ctx, records[i].r1.owner, wins_name_r1);
2833                 ret &= test_wrepl_is_applied(ctx, records[i].r1.owner,
2834                                              wins_name_r1, records[i].r1.apply_expected);
2835
2836                 /*
2837                  * Setup R2
2838                  */
2839                 wins_name_r2->name      = &records[i].name;
2840                 wins_name_r2->flags     = WREPL_NAME_FLAGS(records[i].r2.type,
2841                                                            records[i].r2.state,
2842                                                            records[i].r2.node,
2843                                                            records[i].r2.is_static);
2844                 wins_name_r2->id        = ++records[i].r2.owner->max_version;
2845                 if (wins_name_r2->flags & 2) {
2846                         wins_name_r2->addresses.addresses.num_ips = records[i].r2.num_ips;
2847                         wins_name_r2->addresses.addresses.ips     = discard_const(records[i].r2.ips);
2848                 } else {
2849                         wins_name_r2->addresses.ip = records[i].r2.ips[0].ip;
2850                 }
2851                 wins_name_r2->unknown   = "255.255.255.255";
2852
2853                 /* now apply R2 */
2854                 ret &= test_wrepl_update_one(ctx, records[i].r2.owner, wins_name_r2);
2855                 if (records[i].r1.state == WREPL_STATE_RELEASED) {
2856                         ret &= test_wrepl_is_applied(ctx, records[i].r1.owner,
2857                                                      wins_name_r1, False);
2858                 } else if (records[i].r1.owner != records[i].r2.owner) {
2859                         ret &= test_wrepl_is_applied(ctx, records[i].r1.owner,
2860                                                      wins_name_r1, !records[i].r2.apply_expected);
2861                 }
2862                 if (records[i].r2.state == WREPL_STATE_RELEASED) {
2863                         ret &= test_wrepl_is_applied(ctx, records[i].r2.owner,
2864                                                      wins_name_r2, False);
2865                 } else {
2866                         ret &= test_wrepl_is_applied(ctx, records[i].r2.owner,
2867                                                      wins_name_r2, records[i].r2.apply_expected);
2868                 }
2869
2870                 /* the first one is a cleanup run */
2871                 if (!ret && i == 0) ret = True;
2872
2873                 if (!ret) {
2874                         printf("conflict handled wrong or record[%u]: %s\n", i, records[i].line);
2875                         return ret;
2876                 }
2877         }
2878
2879         return ret;
2880 }
2881
2882 /*
2883   test WINS replication operations
2884 */
2885 BOOL torture_nbt_winsreplication_quick(void)
2886 {
2887         const char *address;
2888         struct nbt_name name;
2889         TALLOC_CTX *mem_ctx = talloc_new(NULL);
2890         NTSTATUS status;
2891         BOOL ret = True;
2892
2893         make_nbt_name_server(&name, lp_parm_string(-1, "torture", "host"));
2894
2895         /* do an initial name resolution to find its IP */
2896         status = resolve_name(&name, mem_ctx, &address, NULL);
2897         if (!NT_STATUS_IS_OK(status)) {
2898                 printf("Failed to resolve %s - %s\n",
2899                        name.name, nt_errstr(status));
2900                 talloc_free(mem_ctx);
2901                 return False;
2902         }
2903
2904         ret &= test_assoc_ctx1(mem_ctx, address);
2905         ret &= test_assoc_ctx2(mem_ctx, address);
2906
2907         talloc_free(mem_ctx);
2908
2909         return ret;
2910 }
2911
2912 /*
2913   test WINS replication operations
2914 */
2915 BOOL torture_nbt_winsreplication(void)
2916 {
2917         const char *address;
2918         struct nbt_name name;
2919         TALLOC_CTX *mem_ctx = talloc_new(NULL);
2920         NTSTATUS status;
2921         BOOL ret = True;
2922         struct test_wrepl_conflict_conn *ctx;
2923
2924         make_nbt_name_server(&name, lp_parm_string(-1, "torture", "host"));
2925
2926         /* do an initial name resolution to find its IP */
2927         status = resolve_name(&name, mem_ctx, &address, NULL);
2928         if (!NT_STATUS_IS_OK(status)) {
2929                 printf("Failed to resolve %s - %s\n",
2930                        name.name, nt_errstr(status));
2931                 talloc_free(mem_ctx);
2932                 return False;
2933         }
2934
2935         ret &= test_assoc_ctx1(mem_ctx, address);
2936         ret &= test_assoc_ctx2(mem_ctx, address);
2937
2938         ret &= test_wins_replication(mem_ctx, address);
2939
2940         ctx = test_create_conflict_ctx(mem_ctx, address);
2941
2942         ret &= test_conflict_same_owner(ctx);
2943         ret &= test_conflict_different_owner(ctx);
2944
2945         talloc_free(mem_ctx);
2946
2947         return ret;
2948 }