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