2 * mergeinfo-test.c -- test the mergeinfo functions
4 * ====================================================================
5 * Copyright (c) 2006-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
22 #include <apr_tables.h>
24 #include "svn_pools.h"
25 #include "svn_types.h"
26 #include "svn_mergeinfo.h"
27 #include "private/svn_mergeinfo_private.h"
28 #include "../svn_test.h"
30 /* A quick way to create error messages. */
32 fail(apr_pool_t
*pool
, const char *fmt
, ...)
38 msg
= apr_pvsprintf(pool
, fmt
, ap
);
41 return svn_error_create(SVN_ERR_TEST_FAILED
, 0, msg
);
44 #define MAX_NBR_RANGES 3
46 /* Verify that INPUT is parsed properly, and returns an error if
47 parsing fails, or incorret parsing is detected. Assumes that INPUT
48 contains only one path -> ranges mapping, and that EXPECTED_RANGES points
49 to the first range in an array whose size is greater than or equal to
50 the number of ranges in INPUTS path -> ranges mapping but less than
51 MAX_NBR_RANGES. If fewer than MAX_NBR_RANGES ranges are present, then the
52 trailing expected_ranges should be have their end revision set to 0. */
54 verify_mergeinfo_parse(const char *input
,
55 const char *expected_path
,
56 const svn_merge_range_t
*expected_ranges
,
60 apr_hash_t
*path_to_merge_ranges
;
63 /* Test valid input. */
64 err
= svn_mergeinfo_parse(&path_to_merge_ranges
, input
, pool
);
65 if (err
|| apr_hash_count(path_to_merge_ranges
) != 1)
66 return svn_error_createf(SVN_ERR_TEST_FAILED
, err
,
67 "svn_mergeinfo_parse (%s) failed unexpectedly",
69 for (hi
= apr_hash_first(pool
, path_to_merge_ranges
); hi
;
70 hi
= apr_hash_next(hi
))
74 apr_array_header_t
*ranges
;
75 svn_merge_range_t
*range
;
78 apr_hash_this(hi
, &path
, NULL
, &val
);
80 if (strcmp((const char *) path
, expected_path
) != 0)
81 return fail(pool
, "svn_mergeinfo_parse (%s) failed to parse the "
82 "correct path (%s)", input
, expected_path
);
84 /* Test each parsed range. */
85 for (j
= 0; j
< ranges
->nelts
; j
++)
87 range
= APR_ARRAY_IDX(ranges
, j
, svn_merge_range_t
*);
88 if (range
->start
!= expected_ranges
[j
].start
89 || range
->end
!= expected_ranges
[j
].end
90 || range
->inheritable
!= expected_ranges
[j
].inheritable
)
91 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
92 "svn_mergeinfo_parse (%s) failed to "
93 "parse the correct range",
97 /* Were we expecting any more ranges? */
98 if (j
< MAX_NBR_RANGES
- 1
99 && !expected_ranges
[j
].end
== 0)
100 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
101 "svn_mergeinfo_parse (%s) failed to "
102 "produce the expected number of ranges",
109 /* Some of our own global variables (for simplicity), which map paths
111 static apr_hash_t
*info1
, *info2
;
113 #define NBR_MERGEINFO_VALS 5
114 /* Valid mergeinfo values. */
115 static const char * const mergeinfo_vals
[NBR_MERGEINFO_VALS
] =
119 "/trunk: 5,7-9,10,11,13,14",
120 "/trunk: 3-10,11*,13,14",
121 "/branch: 1,2-18*,33*"
123 /* Paths corresponding to mergeinfo_vals. */
124 static const char * const mergeinfo_paths
[NBR_MERGEINFO_VALS
] =
132 /* First ranges from the paths identified by mergeinfo_paths. */
133 static svn_merge_range_t mergeinfo_ranges
[NBR_MERGEINFO_VALS
][MAX_NBR_RANGES
] =
137 { {4, 5, TRUE
}, { 6, 11, TRUE
}, {12, 14, TRUE
} },
138 { {2, 10, TRUE
}, {10, 11, FALSE
}, {12, 14, TRUE
} },
139 { {0, 1, TRUE
}, { 1, 18, FALSE
}, {32, 33, FALSE
} }
143 test_parse_single_line_mergeinfo(const char **msg
,
144 svn_boolean_t msg_only
,
145 svn_test_opts_t
*opts
,
150 *msg
= "parse single line mergeinfo";
155 for (i
= 0; i
< NBR_MERGEINFO_VALS
; i
++)
156 SVN_ERR(verify_mergeinfo_parse(mergeinfo_vals
[i
], mergeinfo_paths
[i
],
157 mergeinfo_ranges
[i
], pool
));
162 static const char *single_mergeinfo
= "/trunk: 5,7-9,10,11,13,14";
165 test_mergeinfo_dup(const char **msg
,
166 svn_boolean_t msg_only
,
167 svn_test_opts_t
*opts
,
170 apr_hash_t
*orig_mergeinfo
, *copied_mergeinfo
;
172 apr_array_header_t
*rangelist
;
174 *msg
= "copy a mergeinfo data structure";
179 /* Assure that copies which should be empty turn out that way. */
180 subpool
= svn_pool_create(pool
);
181 orig_mergeinfo
= apr_hash_make(subpool
);
182 copied_mergeinfo
= svn_mergeinfo_dup(orig_mergeinfo
, subpool
);
183 if (apr_hash_count(copied_mergeinfo
) != 0)
184 return fail(pool
, "Copied mergeinfo should be empty");
186 /* Create some mergeinfo, copy it using another pool, then destroy
187 the pool with which the original mergeinfo was created. */
188 SVN_ERR(svn_mergeinfo_parse(&orig_mergeinfo
, single_mergeinfo
, subpool
));
189 copied_mergeinfo
= svn_mergeinfo_dup(orig_mergeinfo
, pool
);
190 svn_pool_destroy(subpool
);
191 if (apr_hash_count(copied_mergeinfo
) != 1)
192 return fail(pool
, "Copied mergeinfo should contain one merge source");
193 rangelist
= apr_hash_get(copied_mergeinfo
, "/trunk", APR_HASH_KEY_STRING
);
195 return fail(pool
, "Expected copied mergeinfo; got nothing");
196 if (rangelist
->nelts
!= 3)
197 return fail(pool
, "Copied mergeinfo should contain 3 revision ranges, "
198 "rather than the %d it contains", rangelist
->nelts
);
204 test_parse_combine_rangeinfo(const char **msg
,
205 svn_boolean_t msg_only
,
206 svn_test_opts_t
*opts
,
209 apr_array_header_t
*result
;
210 svn_merge_range_t
*resultrange
;
212 *msg
= "parse single line mergeinfo and combine ranges";
217 SVN_ERR(svn_mergeinfo_parse(&info1
, single_mergeinfo
, pool
));
219 if (apr_hash_count(info1
) != 1)
220 return fail(pool
, "Wrong number of paths in parsed mergeinfo");
222 result
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
224 return fail(pool
, "Missing path in parsed mergeinfo");
226 /* /trunk should have three ranges, 5-5, 7-11, 13-14 */
227 if (result
->nelts
!= 3)
228 return fail(pool
, "Parsing failed to combine ranges");
230 resultrange
= APR_ARRAY_IDX(result
, 0, svn_merge_range_t
*);
232 if (resultrange
->start
!= 4 || resultrange
->end
!= 5)
233 return fail(pool
, "Range combining produced wrong result");
235 resultrange
= APR_ARRAY_IDX(result
, 1, svn_merge_range_t
*);
237 if (resultrange
->start
!= 6 || resultrange
->end
!= 11)
238 return fail(pool
, "Range combining produced wrong result");
240 resultrange
= APR_ARRAY_IDX(result
, 2, svn_merge_range_t
*);
242 if (resultrange
->start
!= 12 || resultrange
->end
!= 14)
243 return fail(pool
, "Range combining produced wrong result");
249 #define NBR_BROKEN_MERGEINFO_VALS 38
250 /* Invalid mergeinfo values. */
251 static const char * const broken_mergeinfo_vals
[NBR_BROKEN_MERGEINFO_VALS
] =
253 /* Invalid grammar */
255 "/trunk: 5,7-9,10,11,13,14,",
256 "/trunk 5,7-9,10,11,13,14",
257 "/trunk:5 7--9 10 11 13 14",
259 "/trunk:3-6,15,18,9,22",
261 "/trunk:3-6*,15*,18*,9,22*",
263 /* Overlapping revs differing inheritability */
272 /* Overlapping revs same inheritability */
281 /* Reversed revision ranges */
284 "/trunk:3,7-12,22-20,25",
285 "/trunk:3,7,22-20*,25-30",
286 /* Range with same start and end revision */
289 "/trunk:3,7-12,20-20,25",
290 "/trunk:3,7,20-20*,25-30",
291 /* path mapped to range with no revisions */
293 "/trunk:2-9\n/branch:",
296 /* Invalid revisions */
303 test_parse_broken_mergeinfo(const char **msg
,
304 svn_boolean_t msg_only
,
305 svn_test_opts_t
*opts
,
310 *msg
= "parse broken single line mergeinfo";
315 /* Trigger some error(s) with mal-formed input. */
316 for (i
= 0; i
< NBR_BROKEN_MERGEINFO_VALS
; i
++)
318 err
= svn_mergeinfo_parse(&info1
, broken_mergeinfo_vals
[i
], pool
);
319 if (err
== SVN_NO_ERROR
)
321 return fail(pool
, "svn_mergeinfo_parse (%s) failed to detect an error",
322 broken_mergeinfo_vals
[i
]);
324 else if (err
->apr_err
!= SVN_ERR_MERGEINFO_PARSE_ERROR
)
326 svn_error_clear(err
);
327 return fail(pool
, "svn_mergeinfo_parse (%s) returned some error other"
328 " than SVN_ERR_MERGEINFO_PARSE_ERROR",
329 broken_mergeinfo_vals
[i
]);
333 svn_error_clear(err
);
341 static const char *mergeinfo1
= "/trunk: 3,5,7-9,10,11,13,14\n/fred:8-10";
343 #define NBR_RANGELIST_DELTAS 4
346 /* Convert a single svn_merge_range_t * back into an svn_stringbuf_t *. */
348 range_to_string(svn_merge_range_t
*range
,
351 if (range
->start
== range
->end
- 1)
352 return apr_psprintf(pool
, "%ld%s", range
->end
,
354 ? "" : SVN_MERGEINFO_NONINHERITABLE_STR
);
356 return apr_psprintf(pool
, "%ld-%ld%s", range
->start
+ 1,
357 range
->end
, range
->inheritable
358 ? "" : SVN_MERGEINFO_NONINHERITABLE_STR
);
362 /* Verify that ACTUAL_RANGELIST matches EXPECTED_RANGES (an array of
363 NBR_EXPECTED length). Return an error based careful examination if
364 they do not match. FUNC_VERIFIED is the name of the API being
365 verified (e.g. "svn_rangelist_intersect"), while TYPE is a word
366 describing what the ranges being examined represent. */
368 verify_ranges_match(apr_array_header_t
*actual_rangelist
,
369 svn_merge_range_t
*expected_ranges
, int nbr_expected
,
370 const char *func_verified
, const char *type
,
375 if (actual_rangelist
->nelts
!= nbr_expected
)
376 return fail(pool
, "%s should report %d range %ss, but found %d",
377 func_verified
, nbr_expected
, type
, actual_rangelist
->nelts
);
379 for (i
= 0; i
< actual_rangelist
->nelts
; i
++)
381 svn_merge_range_t
*range
= APR_ARRAY_IDX(actual_rangelist
, i
,
382 svn_merge_range_t
*);
383 if (range
->start
!= expected_ranges
[i
].start
384 || range
->end
!= expected_ranges
[i
].end
385 || range
->inheritable
!= expected_ranges
[i
].inheritable
)
386 return fail(pool
, "%s should report range %s, but found %s",
388 range_to_string(&expected_ranges
[i
], pool
),
389 range_to_string(range
, pool
));
394 /* Verify that DELTAS matches EXPECTED_DELTAS (both expected to
395 contain only a rangelist for "/trunk"). Return an error based
396 careful examination if they do not match. FUNC_VERIFIED is the
397 name of the API being verified (e.g. "svn_mergeinfo_diff"), while
398 TYPE is a word describing what the deltas being examined
401 verify_mergeinfo_deltas(apr_hash_t
*deltas
, svn_merge_range_t
*expected_deltas
,
402 const char *func_verified
, const char *type
,
405 apr_array_header_t
*rangelist
;
407 if (apr_hash_count(deltas
) != 1)
408 /* Deltas on "/trunk" expected. */
409 return fail(pool
, "%s should report 1 path %s, but found %d",
410 func_verified
, type
, apr_hash_count(deltas
));
412 rangelist
= apr_hash_get(deltas
, "/trunk", APR_HASH_KEY_STRING
);
413 if (rangelist
== NULL
)
414 return fail(pool
, "%s failed to produce a rangelist for /trunk",
417 return verify_ranges_match(rangelist
, expected_deltas
, NBR_RANGELIST_DELTAS
,
418 func_verified
, type
, pool
);
422 test_diff_mergeinfo(const char **msg
,
423 svn_boolean_t msg_only
,
424 svn_test_opts_t
*opts
,
427 apr_hash_t
*deleted
, *added
, *from
, *to
;
428 svn_merge_range_t expected_rangelist_deletions
[NBR_RANGELIST_DELTAS
] =
429 { {6, 7, TRUE
}, {8, 9, TRUE
}, {10, 11, TRUE
}, {32, 34, TRUE
} };
430 svn_merge_range_t expected_rangelist_additions
[NBR_RANGELIST_DELTAS
] =
431 { {1, 2, TRUE
}, {4, 6, TRUE
}, {12, 16, TRUE
}, {29, 30, TRUE
} };
433 *msg
= "diff of mergeinfo";
437 SVN_ERR(svn_mergeinfo_parse(&from
, "/trunk: 1,3-4,7,9,11-12,31-34", pool
));
438 SVN_ERR(svn_mergeinfo_parse(&to
, "/trunk: 1-6,12-16,30-32", pool
));
439 /* On /trunk: deleted (7, 9, 11, 33-34) and added (2, 5-6, 13-16, 30) */
440 SVN_ERR(svn_mergeinfo_diff(&deleted
, &added
, from
, to
,
443 /* Verify calculation of range list deltas. */
444 SVN_ERR(verify_mergeinfo_deltas(deleted
, expected_rangelist_deletions
,
445 "svn_mergeinfo_diff", "deletion", pool
));
446 SVN_ERR(verify_mergeinfo_deltas(added
, expected_rangelist_additions
,
447 "svn_mergeinfo_diff", "addition", pool
));
453 test_rangelist_reverse(const char **msg
,
454 svn_boolean_t msg_only
,
455 svn_test_opts_t
*opts
,
458 apr_array_header_t
*rangelist
;
459 svn_merge_range_t expected_rangelist
[3] =
460 { {10, 9, TRUE
}, {7, 4, TRUE
}, {3, 2, TRUE
} };
462 *msg
= "reversal of rangelist";
466 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 3,5-7,10", pool
));
467 rangelist
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
469 SVN_ERR(svn_rangelist_reverse(rangelist
, pool
));
471 return verify_ranges_match(rangelist
, expected_rangelist
, 3,
472 "svn_rangelist_reverse", "reversal", pool
);
476 test_rangelist_intersect(const char **msg
,
477 svn_boolean_t msg_only
,
478 svn_test_opts_t
*opts
,
481 apr_array_header_t
*rangelist1
, *rangelist2
, *intersection
;
482 svn_merge_range_t expected_intersection
[] =
483 { {0, 1, TRUE
}, {2, 4, TRUE
}, {11, 12, TRUE
}, {30, 32, TRUE
},
486 *msg
= "intersection of rangelists";
490 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 1-6,12-16,30-32,40-42", pool
));
491 SVN_ERR(svn_mergeinfo_parse(&info2
, "/trunk: 1,3-4,7,9,11-12,31-34,38-44",
493 rangelist1
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
494 rangelist2
= apr_hash_get(info2
, "/trunk", APR_HASH_KEY_STRING
);
496 SVN_ERR(svn_rangelist_intersect(&intersection
, rangelist1
, rangelist2
,
499 return verify_ranges_match(intersection
, expected_intersection
, 5,
500 "svn_rangelist_intersect", "intersect", pool
);
504 test_mergeinfo_intersect(const char **msg
,
505 svn_boolean_t msg_only
,
506 svn_test_opts_t
*opts
,
509 svn_merge_range_t expected_intersection
[3] =
510 { {0, 1, TRUE
}, {2, 4, TRUE
}, {11, 12, TRUE
} };
511 apr_array_header_t
*rangelist
;
512 apr_hash_t
*intersection
;
514 *msg
= "intersection of mergeinfo";
518 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 1-6,12-16\n/foo: 31", pool
));
519 SVN_ERR(svn_mergeinfo_parse(&info2
, "/trunk: 1,3-4,7,9,11-12", pool
));
521 SVN_ERR(svn_mergeinfo_intersect(&intersection
, info1
, info2
, pool
));
522 if (apr_hash_count(intersection
) != 1)
523 return fail(pool
, "Unexpected number of rangelists in mergeinfo "
524 "intersection: Expected %d, found %d", 1,
525 apr_hash_count(intersection
));
527 rangelist
= apr_hash_get(intersection
, "/trunk", APR_HASH_KEY_STRING
);
528 return verify_ranges_match(rangelist
, expected_intersection
, 3,
529 "svn_rangelist_intersect", "intersect", pool
);
533 test_merge_mergeinfo(const char **msg
,
534 svn_boolean_t msg_only
,
535 svn_test_opts_t
*opts
,
540 /* Structures and constants for test_merge_mergeinfo() */
541 /* Number of svn_mergeinfo_merge test sets */
542 #define NBR_MERGEINFO_MERGES 12
544 /* Maximum number of expected paths in the results
545 of the svn_mergeinfo_merge tests */
546 #define MAX_NBR_MERGEINFO_PATHS 4
548 /* Maximum number of expected ranges in the results
549 of the svn_mergeinfo_merge tests */
550 #define MAX_NBR_MERGEINFO_RANGES 10
552 /* Struct to store a path and it's expected ranges,
553 i.e. the expected result of an svn_mergeinfo_merge
555 struct mergeinfo_merge_path_range
558 svn_merge_range_t expected_rngs
[MAX_NBR_MERGEINFO_RANGES
];
561 /* Struct for svn_mergeinfo_merge test data.
562 If MERGEINFO1 and MERGEINFO2 are parsed to a hash with
563 svn_mergeinfo_parse() and then merged with svn_mergeinfo_merge(),
564 the resulting hash should have EXPECTED_PATHS number of paths
565 mapped to rangelists and each mapping is described by PATH_RNGS
566 where PATH_RNGS->PATH is not NULL. */
567 struct mergeinfo_merge_test_data
569 const char *mergeinfo1
;
570 const char *mergeinfo2
;
572 struct mergeinfo_merge_path_range path_rngs
[MAX_NBR_MERGEINFO_PATHS
];
575 static struct mergeinfo_merge_test_data mergeinfo
[NBR_MERGEINFO_MERGES
] =
577 /* One path, intersecting inheritable ranges */
580 { {"/trunk", { {4, 10, TRUE
} } } } },
582 /* One path, intersecting non-inheritable ranges */
585 { {"/trunk", { {4, 10, FALSE
} } } } },
587 /* One path, intersecting ranges with different inheritability */
590 { {"/trunk", { {4, 10, TRUE
} } } } },
592 /* One path, intersecting ranges with different inheritability */
595 { {"/trunk", { {4, 5, FALSE
}, {5, 6, TRUE
}, {6, 10, FALSE
} } } } },
597 /* Adjacent ranges all inheritable ranges */
598 { "/trunk: 1,3,5-11,13",
599 "/trunk: 2,4,12,14-22", 1,
600 { {"/trunk", { {0, 22, TRUE
} } } } },
602 /* Adjacent ranges all non-inheritable ranges */
603 { "/trunk: 1*,3*,5-11*,13*",
604 "/trunk: 2*,4*,12*,14-22*", 1,
605 { {"/trunk", { {0, 22, FALSE
} } } } },
607 /* Adjacent ranges differing inheritability */
608 { "/trunk: 1*,3*,5-11*,13*",
609 "/trunk: 2,4,12,14-22", 1,
610 { {"/trunk", { { 0, 1, FALSE
}, { 1, 2, TRUE
},
611 { 2, 3, FALSE
}, { 3, 4, TRUE
},
612 { 4, 11, FALSE
}, {11, 12, TRUE
},
613 {12, 13, FALSE
}, {13, 22, TRUE
} } } } },
615 /* Adjacent ranges differing inheritability */
616 { "/trunk: 1,3,5-11,13",
617 "/trunk: 2*,4*,12*,14-22*", 1,
618 { {"/trunk", { { 0, 1, TRUE
}, { 1, 2, FALSE
},
619 { 2, 3, TRUE
}, { 3, 4, FALSE
},
620 { 4, 11, TRUE
}, {11, 12, FALSE
},
621 {12, 13, TRUE
}, {13, 22, FALSE
} } } } },
623 /* Two paths all inheritable ranges */
624 { "/trunk: 3,5,7-9,10,11,13,14\n/fred:8-10",
625 "/trunk: 1-4,6\n/fred:9-12", 2,
626 { {"/trunk", { {0, 11, TRUE
}, {12, 14, TRUE
} } },
627 {"/fred", { {7, 12, TRUE
} } } } },
629 /* Two paths all non-inheritable ranges */
630 { "/trunk: 3*,5*,7-9*,10*,11*,13*,14*\n/fred:8-10*",
631 "/trunk: 1-4*,6*\n/fred:9-12*", 2,
632 { {"/trunk", { {0, 11, FALSE
}, {12, 14, FALSE
} } },
633 {"/fred", { {7, 12, FALSE
} } } } },
635 /* Two paths mixed inheritability */
636 { "/trunk: 3,5*,7-9,10,11*,13,14\n/fred:8-10",
637 "/trunk: 1-4,6\n/fred:9-12*", 2,
638 { {"/trunk", { { 0, 4, TRUE
}, { 4, 5, FALSE
}, {5, 10, TRUE
},
639 {10, 11, FALSE
}, {12, 14, TRUE
} } },
640 {"/fred", { { 7, 10, TRUE
}, {10, 12, FALSE
} } } } },
642 /* A slew of different paths but no ranges to be merged */
643 { "/trunk: 3,5-9*\n/betty: 2-4",
644 "/fred: 1-18\n/barney: 1,3-43", 4,
645 { {"/trunk", { {2, 3, TRUE
}, {4, 9, FALSE
} } },
646 {"/betty", { {1, 4, TRUE
} } },
647 {"/barney", { {0, 1, TRUE
}, {2, 43, TRUE
} } },
648 {"/fred", { {0, 18, TRUE
} } } } }
651 *msg
= "merging of mergeinfo hashs";
655 for (i
= 0; i
< NBR_MERGEINFO_MERGES
; i
++)
658 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo
[i
].mergeinfo1
, pool
));
659 SVN_ERR(svn_mergeinfo_parse(&info2
, mergeinfo
[i
].mergeinfo2
, pool
));
660 SVN_ERR(svn_mergeinfo_merge(info1
, info2
, pool
));
661 if (mergeinfo
[i
].expected_paths
!= apr_hash_count(info1
))
662 return fail(pool
, "Wrong number of paths in merged mergeinfo");
663 for (j
= 0; j
< mergeinfo
[i
].expected_paths
; j
++)
666 apr_array_header_t
*rangelist
=
667 apr_hash_get(info1
, mergeinfo
[i
].path_rngs
[j
].path
,
668 APR_HASH_KEY_STRING
);
670 return fail(pool
, "Missing path '%s' in merged mergeinfo",
671 mergeinfo
[i
].path_rngs
->path
);
672 for (k
= 0; k
< rangelist
->nelts
; k
++)
674 svn_merge_range_t
*ranges
=
675 APR_ARRAY_IDX(rangelist
, k
, svn_merge_range_t
*);
677 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].start
679 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].end
680 || ranges
->inheritable
681 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].inheritable
)
684 "Range'%i-%i%s' not found in merged mergeinfo",
685 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].start
,
686 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].end
,
687 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].inheritable
690 /* Were more ranges expected? */
691 if (k
< MAX_NBR_MERGEINFO_RANGES
692 && mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].start
!= 0)
694 "Not all expected ranges found in merged mergeinfo");
702 test_remove_rangelist(const char **msg
,
703 svn_boolean_t msg_only
,
704 svn_test_opts_t
*opts
,
708 svn_error_t
*err
, *child_err
;
709 apr_array_header_t
*output
, *eraser
, *whiteboard
;
711 /* Struct for svn_rangelist_remove test data.
712 Parse WHITEBOARD and ERASER to hashes and then get the rangelist for
715 Remove ERASER's rangelist from WHITEBOARD's twice, once while
716 considering inheritance and once while not. In the first case the
717 resulting rangelist should have EXPECTED_RANGES_CONSIDER_INHERITANCE
718 number of ranges and these ranges should match the ranges in
719 EXPECTED_REMOVED_CONSIDER_INHERITANCE. In the second case there
720 should be EXPECTED_RANGES_IGNORE_INHERITANCE number of ranges and
721 these should match EXPECTED_REMOVED_IGNORE_INHERITANCE */
722 struct rangelist_remove_test_data
724 const char *whiteboard
;
726 int expected_ranges_consider_inheritance
;
727 svn_merge_range_t expected_removed_consider_inheritance
[10];
728 int expected_ranges_ignore_inheritance
;
729 svn_merge_range_t expected_removed_ignore_inheritance
[10];
732 #define SIZE_OF_RANGE_REMOVE_TEST_ARRAY 15
734 /* The actual test data */
735 struct rangelist_remove_test_data test_data
[SIZE_OF_RANGE_REMOVE_TEST_ARRAY
] =
737 /* Eraser is a proper subset of whiteboard */
738 {"/A: 1-44", "/A: 5", 2, { {0, 4, TRUE
}, {5, 44, TRUE
}},
739 2, { {0, 4, TRUE
}, {5, 44, TRUE
}}},
740 {"/A: 1-44*", "/A: 5", 1, { {0, 44, FALSE
} },
741 2, { {0, 4, FALSE
}, {5, 44, FALSE
}}},
742 {"/A: 1-44", "/A: 5*", 1, { {0, 44, TRUE
} },
743 2, { {0, 4, TRUE
}, {5, 44, TRUE
}}},
744 {"/A: 1-44*", "/A: 5*", 2, { {0, 4, FALSE
}, {5, 44, FALSE
}},
745 2, { {0, 4, FALSE
}, {5, 44, FALSE
}}},
746 /* Non-intersecting ranges...nothing is removed */
747 {"/A: 2-9,14-19", "/A: 12", 2, { {1, 9, TRUE
}, {13, 19, TRUE
}},
748 2, { {1, 9, TRUE
}, {13, 19, TRUE
}}},
749 {"/A: 2-9*,14-19*", "/A: 12", 2, { {1, 9, FALSE
}, {13, 19, FALSE
}},
750 2, { {1, 9, FALSE
}, {13, 19, FALSE
}}},
751 {"/A: 2-9,14-19", "/A: 12*", 2, { {1, 9, TRUE
}, {13, 19, TRUE
}},
752 2, { {1, 9, TRUE
}, {13, 19, TRUE
}}},
753 {"/A: 2-9*,14-19*", "/A: 12*", 2, { {1, 9, FALSE
}, {13, 19, FALSE
}},
754 2, { {1, 9, FALSE
}, {13, 19, FALSE
}}},
755 /* Eraser overlaps whiteboard */
756 {"/A: 1,9-17", "/A: 12-20", 2, { {0, 1, TRUE
}, {8, 11, TRUE
}},
757 2, { {0, 1, TRUE
}, {8, 11, TRUE
}}},
758 {"/A: 1,9-17*", "/A: 12-20", 2, { {0, 1, TRUE
}, {8, 17, FALSE
}},
759 2, { {0, 1, TRUE
}, {8, 11, FALSE
}}},
760 {"/A: 1,9-17", "/A: 12-20*", 2, { {0, 1, TRUE
}, {8, 17, TRUE
}},
761 2, { {0, 1, TRUE
}, {8, 11, TRUE
}}},
762 {"/A: 1,9-17*", "/A: 12-20*", 2, { {0, 1, TRUE
}, {8, 11, FALSE
}},
763 2, { {0, 1, TRUE
}, {8, 11, FALSE
}}},
764 /* Empty mergeinfo (i.e. empty rangelist) */
765 {"", "", 0, { {0, 0, FALSE
}},
766 0, { {0, 0, FALSE
}}},
767 {"", "/A: 5-8,10-100", 0, { {0, 0, FALSE
}},
768 0, { {0, 0, FALSE
}}},
769 {"/A: 5-8,10-100", "", 2, { {4, 8, TRUE
}, {9, 100, TRUE
}},
770 2, { {4, 8, TRUE
}, {9, 100, TRUE
}}}
773 *msg
= "remove rangelists";
774 err
= child_err
= SVN_NO_ERROR
;
775 for (j
= 0; j
< 2; j
++)
777 for (i
= 0; i
< SIZE_OF_RANGE_REMOVE_TEST_ARRAY
; i
++)
779 int expected_nbr_ranges
;
780 svn_merge_range_t
*expected_ranges
;
782 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).eraser
, pool
));
783 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).whiteboard
, pool
));
784 eraser
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
785 whiteboard
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
787 /* Represent empty mergeinfo with an empty rangelist. */
789 eraser
= apr_array_make(pool
, 0, sizeof(*eraser
));
790 if (whiteboard
== NULL
)
791 whiteboard
= apr_array_make(pool
, 0, sizeof(*whiteboard
));
793 /* First pass try removal considering inheritance, on the
794 second pass ignore it. */
797 expected_nbr_ranges
= (test_data
[i
]).expected_ranges_consider_inheritance
;
798 expected_ranges
= (test_data
[i
]).expected_removed_consider_inheritance
;
803 expected_nbr_ranges
= (test_data
[i
]).expected_ranges_ignore_inheritance
;
804 expected_ranges
= (test_data
[i
]).expected_removed_ignore_inheritance
;
807 SVN_ERR(svn_rangelist_remove(&output
, eraser
, whiteboard
,
808 j
== 0 ? TRUE
: FALSE
,
810 child_err
= verify_ranges_match(output
, expected_ranges
,
813 "svn_rangelist_remove "
817 /* Collect all the errors rather than returning on the first. */
821 svn_error_compose(err
, child_err
);
830 #define RANDOM_REV_ARRAY_LENGTH 100
832 /* Random number seed. */
833 static apr_uint32_t random_rev_array_seed
;
835 /* Fill 3/4 of the array with 1s. */
837 randomly_fill_rev_array(svn_boolean_t
*revs
)
840 for (i
= 0; i
< RANDOM_REV_ARRAY_LENGTH
; i
++)
842 apr_uint32_t next
= svn_test_rand(&random_rev_array_seed
);
843 revs
[i
] = (next
< 0x40000000) ? 0 : 1;
848 rev_array_to_rangelist(apr_array_header_t
**rangelist
,
852 svn_stringbuf_t
*buf
= svn_stringbuf_create("/trunk: ", pool
);
853 svn_boolean_t first
= TRUE
;
854 apr_hash_t
*mergeinfo
;
857 for (i
= 0; i
< RANDOM_REV_ARRAY_LENGTH
; i
++)
864 svn_stringbuf_appendcstr(buf
, ",");
865 svn_stringbuf_appendcstr(buf
, apr_psprintf(pool
, "%d", i
));
869 SVN_ERR(svn_mergeinfo_parse(&mergeinfo
, buf
->data
, pool
));
870 *rangelist
= apr_hash_get(mergeinfo
, "/trunk", APR_HASH_KEY_STRING
);
876 test_rangelist_remove_randomly(const char **msg
,
877 svn_boolean_t msg_only
,
878 svn_test_opts_t
*opts
,
882 apr_pool_t
*iterpool
;
884 *msg
= "test rangelist remove with random data";
888 random_rev_array_seed
= (apr_uint32_t
) apr_time_now();
890 iterpool
= svn_pool_create(pool
);
892 for (i
= 0; i
< 20; i
++)
894 svn_boolean_t first_revs
[RANDOM_REV_ARRAY_LENGTH
],
895 second_revs
[RANDOM_REV_ARRAY_LENGTH
],
896 expected_revs
[RANDOM_REV_ARRAY_LENGTH
];
897 apr_array_header_t
*first_rangelist
, *second_rangelist
,
898 *expected_rangelist
, *actual_rangelist
;
899 /* There will be at most RANDOM_REV_ARRAY_LENGTH ranges in
900 expected_rangelist. */
901 svn_merge_range_t expected_range_array
[RANDOM_REV_ARRAY_LENGTH
];
904 svn_pool_clear(iterpool
);
906 randomly_fill_rev_array(first_revs
);
907 randomly_fill_rev_array(second_revs
);
908 for (j
= 0; j
< RANDOM_REV_ARRAY_LENGTH
; j
++)
909 expected_revs
[j
] = second_revs
[j
] && !first_revs
[j
];
911 SVN_ERR(rev_array_to_rangelist(&first_rangelist
, first_revs
, iterpool
));
912 SVN_ERR(rev_array_to_rangelist(&second_rangelist
, second_revs
, iterpool
));
913 SVN_ERR(rev_array_to_rangelist(&expected_rangelist
, expected_revs
,
916 for (j
= 0; j
< expected_rangelist
->nelts
; j
++)
918 expected_range_array
[j
] = *(APR_ARRAY_IDX(expected_rangelist
, j
,
919 svn_merge_range_t
*));
922 SVN_ERR(svn_rangelist_remove(&actual_rangelist
, first_rangelist
,
923 second_rangelist
, TRUE
, iterpool
));
925 SVN_ERR(verify_ranges_match(actual_rangelist
,
926 expected_range_array
,
927 expected_rangelist
->nelts
,
928 "svn_rangelist_remove random call",
929 "remove", iterpool
));
932 svn_pool_destroy(iterpool
);
938 test_rangelist_intersect_randomly(const char **msg
,
939 svn_boolean_t msg_only
,
940 svn_test_opts_t
*opts
,
944 apr_pool_t
*iterpool
;
946 *msg
= "test rangelist intersect with random data";
950 random_rev_array_seed
= (apr_uint32_t
) apr_time_now();
952 iterpool
= svn_pool_create(pool
);
954 for (i
= 0; i
< 20; i
++)
956 svn_boolean_t first_revs
[RANDOM_REV_ARRAY_LENGTH
],
957 second_revs
[RANDOM_REV_ARRAY_LENGTH
],
958 expected_revs
[RANDOM_REV_ARRAY_LENGTH
];
959 apr_array_header_t
*first_rangelist
, *second_rangelist
,
960 *expected_rangelist
, *actual_rangelist
;
961 /* There will be at most RANDOM_REV_ARRAY_LENGTH ranges in
962 expected_rangelist. */
963 svn_merge_range_t expected_range_array
[RANDOM_REV_ARRAY_LENGTH
];
966 svn_pool_clear(iterpool
);
968 randomly_fill_rev_array(first_revs
);
969 randomly_fill_rev_array(second_revs
);
970 for (j
= 0; j
< RANDOM_REV_ARRAY_LENGTH
; j
++)
971 expected_revs
[j
] = second_revs
[j
] && first_revs
[j
];
973 SVN_ERR(rev_array_to_rangelist(&first_rangelist
, first_revs
, iterpool
));
974 SVN_ERR(rev_array_to_rangelist(&second_rangelist
, second_revs
, iterpool
));
975 SVN_ERR(rev_array_to_rangelist(&expected_rangelist
, expected_revs
,
978 for (j
= 0; j
< expected_rangelist
->nelts
; j
++)
980 expected_range_array
[j
] = *(APR_ARRAY_IDX(expected_rangelist
, j
,
981 svn_merge_range_t
*));
984 SVN_ERR(svn_rangelist_intersect(&actual_rangelist
, first_rangelist
,
985 second_rangelist
, iterpool
));
987 SVN_ERR(verify_ranges_match(actual_rangelist
,
988 expected_range_array
,
989 expected_rangelist
->nelts
,
990 "svn_rangelist_intersect random call",
991 "intersect", iterpool
));
994 svn_pool_destroy(iterpool
);
999 /* ### Share code with test_diff_mergeinfo() and test_remove_rangelist(). */
1000 static svn_error_t
*
1001 test_remove_mergeinfo(const char **msg
,
1002 svn_boolean_t msg_only
,
1003 svn_test_opts_t
*opts
,
1006 apr_hash_t
*output
, *whiteboard
, *eraser
;
1007 svn_merge_range_t expected_rangelist_remainder
[NBR_RANGELIST_DELTAS
] =
1008 { {6, 7, TRUE
}, {8, 9, TRUE
}, {10, 11, TRUE
}, {32, 34, TRUE
} };
1010 *msg
= "remove of mergeinfo";
1012 return SVN_NO_ERROR
;
1014 SVN_ERR(svn_mergeinfo_parse(&whiteboard
,
1015 "/trunk: 1,3-4,7,9,11-12,31-34", pool
));
1016 SVN_ERR(svn_mergeinfo_parse(&eraser
, "/trunk: 1-6,12-16,30-32", pool
));
1018 /* Leftover on /trunk should be the set (7, 9, 11, 33-34) */
1019 SVN_ERR(svn_mergeinfo_remove(&output
, eraser
, whiteboard
, pool
));
1021 /* Verify calculation of range list remainder. */
1022 return verify_mergeinfo_deltas(output
, expected_rangelist_remainder
,
1023 "svn_mergeinfo_remove", "leftover", pool
);
1025 #undef NBR_RANGELIST_DELTAS
1027 static svn_error_t
*
1028 test_rangelist_to_string(const char **msg
,
1029 svn_boolean_t msg_only
,
1030 svn_test_opts_t
*opts
,
1033 apr_array_header_t
*result
;
1034 svn_string_t
*output
;
1035 svn_string_t
*expected
= svn_string_create("3,5,7-11,13-14", pool
);
1037 *msg
= "turning rangelist back into a string";
1040 return SVN_NO_ERROR
;
1042 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo1
, pool
));
1044 result
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
1046 return fail(pool
, "Missing path in parsed mergeinfo");
1048 SVN_ERR(svn_rangelist_to_string(&output
, result
, pool
));
1050 if (svn_string_compare(expected
, output
) != TRUE
)
1051 return fail(pool
, "Rangelist string not what we expected");
1053 return SVN_NO_ERROR
;
1056 static svn_error_t
*
1057 test_mergeinfo_to_string(const char **msg
,
1058 svn_boolean_t msg_only
,
1059 svn_test_opts_t
*opts
,
1062 svn_string_t
*output
;
1063 svn_string_t
*expected
;
1064 expected
= svn_string_create("/fred:8-10\n/trunk:3,5,7-11,13-14", pool
);
1066 *msg
= "turning mergeinfo back into a string";
1069 return SVN_NO_ERROR
;
1071 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo1
, pool
));
1073 SVN_ERR(svn_mergeinfo_to_string(&output
, info1
, pool
));
1075 if (svn_string_compare(expected
, output
) != TRUE
)
1076 return fail(pool
, "Mergeinfo string not what we expected");
1078 return SVN_NO_ERROR
;
1082 static svn_error_t
*
1083 test_rangelist_merge(const char **msg
,
1084 svn_boolean_t msg_only
,
1085 svn_test_opts_t
*opts
,
1089 svn_error_t
*err
, *child_err
;
1090 apr_array_header_t
*rangelist1
, *rangelist2
;
1092 /* Struct for svn_rangelist_merge test data. Similar to
1093 mergeinfo_merge_test_data struct in svn_mergeinfo_merge() test. */
1094 struct rangelist_merge_test_data
1096 const char *mergeinfo1
;
1097 const char *mergeinfo2
;
1098 int expected_ranges
;
1099 svn_merge_range_t expected_merge
[6];
1102 #define SIZE_OF_RANGE_MERGE_TEST_ARRAY 59
1103 /* The actual test data. */
1104 struct rangelist_merge_test_data test_data
[SIZE_OF_RANGE_MERGE_TEST_ARRAY
] =
1106 /* Non-intersecting ranges */
1107 {"/A: 1-44", "/A: 70-101", 2, {{ 0, 44, TRUE
}, {69, 101, TRUE
}}},
1108 {"/A: 1-44*", "/A: 70-101", 2, {{ 0, 44, FALSE
}, {69, 101, TRUE
}}},
1109 {"/A: 1-44", "/A: 70-101*", 2, {{ 0, 44, TRUE
}, {69, 101, FALSE
}}},
1110 {"/A: 1-44*", "/A: 70-101*", 2, {{ 0, 44, FALSE
}, {69, 101, FALSE
}}},
1111 {"/A: 70-101", "/A: 1-44", 2, {{ 0, 44, TRUE
}, {69, 101, TRUE
}}},
1112 {"/A: 70-101*", "/A: 1-44", 2, {{ 0, 44, TRUE
}, {69, 101, FALSE
}}},
1113 {"/A: 70-101", "/A: 1-44*", 2, {{ 0, 44, FALSE
}, {69, 101, TRUE
}}},
1114 {"/A: 70-101*", "/A: 1-44*", 2, {{ 0, 44, FALSE
}, {69, 101, FALSE
}}},
1116 /* Intersecting ranges with same starting and ending revisions */
1117 {"/A: 4-20", "/A: 4-20", 1, {{3, 20, TRUE
}}},
1118 {"/A: 4-20*", "/A: 4-20", 1, {{3, 20, TRUE
}}},
1119 {"/A: 4-20", "/A: 4-20*", 1, {{3, 20, TRUE
}}},
1120 {"/A: 4-20*", "/A: 4-20*", 1, {{3, 20, FALSE
}}},
1122 /* Intersecting ranges with same starting revision */
1123 {"/A: 6-17", "/A: 6-12", 1, {{5, 17, TRUE
}}},
1124 {"/A: 6-17*", "/A: 6-12", 2, {{5, 12, TRUE
}, {12, 17, FALSE
}}},
1125 {"/A: 6-17", "/A: 6-12*", 1, {{5, 17, TRUE
}}},
1126 {"/A: 6-17*", "/A: 6-12*", 1, {{5, 17, FALSE
}}},
1127 {"/A: 6-12", "/A: 6-17", 1, {{5, 17, TRUE
}}},
1128 {"/A: 6-12*", "/A: 6-17", 1, {{5, 17, TRUE
}}},
1129 {"/A: 6-12", "/A: 6-17*", 2, {{5, 12, TRUE
}, {12, 17, FALSE
}}},
1130 {"/A: 6-12*", "/A: 6-17*", 1, {{5, 17, FALSE
}}},
1132 /* Intersecting ranges with same ending revision */
1133 {"/A: 5-77", "/A: 44-77", 1, {{4, 77, TRUE
}}},
1134 {"/A: 5-77*", "/A: 44-77", 2, {{4, 43, FALSE
}, {43, 77, TRUE
}}},
1135 {"/A: 5-77", "/A: 44-77*", 1, {{4, 77, TRUE
}}},
1136 {"/A: 5-77*", "/A: 44-77*", 1, {{4, 77, FALSE
}}},
1137 {"/A: 44-77", "/A: 5-77", 1, {{4, 77, TRUE
}}},
1138 {"/A: 44-77*", "/A: 5-77", 1, {{4, 77, TRUE
}}},
1139 {"/A: 44-77", "/A: 5-77*", 2, {{4, 43, FALSE
}, {43, 77, TRUE
}}},
1140 {"/A: 44-77*", "/A: 5-77*", 1, {{4, 77, FALSE
}}},
1142 /* Intersecting ranges with different starting and ending revision
1143 where one range is a proper subset of the other. */
1144 {"/A: 12-24", "/A: 20-23", 1, {{11, 24, TRUE
}}},
1145 {"/A: 12-24*", "/A: 20-23", 3, {{11, 19, FALSE
}, {19, 23, TRUE
},
1147 {"/A: 12-24", "/A: 20-23*", 1, {{11, 24, TRUE
}}},
1148 {"/A: 12-24*", "/A: 20-23*", 1, {{11, 24, FALSE
}}},
1149 {"/A: 20-23", "/A: 12-24", 1, {{11, 24, TRUE
}}},
1150 {"/A: 20-23*", "/A: 12-24", 1, {{11, 24, TRUE
}}},
1151 {"/A: 20-23", "/A: 12-24*", 3, {{11, 19, FALSE
}, {19, 23, TRUE
},
1153 {"/A: 20-23*", "/A: 12-24*", 1, {{11, 24, FALSE
}}},
1155 /* Intersecting ranges with different starting and ending revision
1156 where neither range is a proper subset of the other. */
1157 {"/A: 50-73", "/A: 60-99", 1, {{49, 99, TRUE
}}},
1158 {"/A: 50-73*", "/A: 60-99", 2, {{49, 59, FALSE
}, {59, 99, TRUE
}}},
1159 {"/A: 50-73", "/A: 60-99*", 2, {{49, 73, TRUE
}, {73, 99, FALSE
}}},
1160 {"/A: 50-73*", "/A: 60-99*", 1, {{49, 99, FALSE
}}},
1161 {"/A: 60-99", "/A: 50-73", 1, {{49, 99, TRUE
}}},
1162 {"/A: 60-99*", "/A: 50-73", 2, {{49, 73, TRUE
}, {73, 99, FALSE
}}},
1163 {"/A: 60-99", "/A: 50-73*", 2, {{49, 59, FALSE
}, {59, 99, TRUE
}}},
1164 {"/A: 60-99*", "/A: 50-73*", 1, {{49, 99, FALSE
}}},
1166 /* Multiple ranges. */
1167 {"/A: 1-5,7,12-13", "/A: 2-17", 1, {{0, 17, TRUE
}}},
1168 {"/A: 1-5*,7*,12-13*", "/A: 2-17*", 1, {{0, 17, FALSE
}}},
1170 {"/A: 1-5,7,12-13", "/A: 2-17*", 6,
1171 {{0, 5, TRUE
}, { 5, 6, FALSE
}, { 6, 7, TRUE
},
1172 {7, 11, FALSE
}, {11, 13, TRUE
}, {13, 17, FALSE
}}},
1174 {"/A: 1-5*,7*,12-13*", "/A: 2-17", 2,
1175 {{0, 1, FALSE
}, {1, 17, TRUE
}}},
1177 {"/A: 2-17", "/A: 1-5,7,12-13", 1, {{0, 17, TRUE
}}},
1178 {"/A: 2-17*", "/A: 1-5*,7*,12-13*", 1, {{0, 17, FALSE
}}},
1180 {"/A: 2-17*", "/A: 1-5,7,12-13", 6,
1181 {{0, 5, TRUE
}, { 5, 6, FALSE
}, { 6, 7, TRUE
},
1182 {7, 11, FALSE
}, {11, 13, TRUE
}, {13, 17, FALSE
}}},
1184 {"/A: 2-17", "/A: 1-5*,7*,12-13*", 2,
1185 {{0, 1, FALSE
}, {1, 17, TRUE
}}},
1187 /* A rangelist merged with an empty rangelist should equal the
1188 non-empty rangelist but in compacted form. */
1189 {"/A: 1-44,45,46,47-50", "", 1, {{ 0, 50, TRUE
}}},
1190 {"/A: 1,2,3,4,5,6,7,8", "", 1, {{ 0, 8, TRUE
}}},
1191 {"/A: 6-10,12-13,14,15,16-22", "", 2,
1192 {{ 5, 10, TRUE
}, { 11, 22, TRUE
}}},
1193 {"", "/A: 1-44,45,46,47-50", 1, {{ 0, 50, TRUE
}}},
1194 {"", "/A: 1,2,3,4,5,6,7,8", 1, {{ 0, 8, TRUE
}}},
1195 {"", "/A: 6-10,12-13,14,15,16-22", 2,
1196 {{ 5, 10, TRUE
}, { 11, 22, TRUE
}}},
1198 /* An empty rangelist merged with an empty rangelist is, drum-roll
1199 please, an empty rangelist. */
1200 {"", "", 0, {{0, 0, FALSE
}}}
1202 *msg
= "merge of rangelists";
1204 return SVN_NO_ERROR
;
1206 err
= child_err
= SVN_NO_ERROR
;
1207 for (i
= 0; i
< SIZE_OF_RANGE_MERGE_TEST_ARRAY
; i
++)
1209 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).mergeinfo1
, pool
));
1210 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).mergeinfo2
, pool
));
1211 rangelist1
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
1212 rangelist2
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
1214 /* Create empty rangelists if necessary. */
1215 if (rangelist1
== NULL
)
1216 rangelist1
= apr_array_make(pool
, 0, sizeof(svn_merge_range_t
*));
1217 if (rangelist2
== NULL
)
1218 rangelist2
= apr_array_make(pool
, 0, sizeof(svn_merge_range_t
*));
1220 SVN_ERR(svn_rangelist_merge(&rangelist1
, rangelist2
, pool
));
1221 child_err
= verify_ranges_match(rangelist1
,
1222 (test_data
[i
]).expected_merge
,
1223 (test_data
[i
]).expected_ranges
,
1225 "svn_rangelist_merge "
1229 /* Collect all the errors rather than returning on the first. */
1233 svn_error_compose(err
, child_err
);
1241 static svn_error_t
*
1242 test_rangelist_diff(const char **msg
,
1243 svn_boolean_t msg_only
,
1244 svn_test_opts_t
*opts
,
1248 svn_error_t
*err
, *child_err
;
1249 apr_array_header_t
*from
, *to
, *added
, *deleted
;
1251 /* Structure containing two ranges to diff and the expected output of the
1252 diff both when considering and ignoring range inheritance. */
1253 struct rangelist_diff_test_data
1255 /* svn:mergeinfo string representations */
1259 /* Expected results for performing svn_rangelist_diff
1260 while considering differences in inheritability to be real
1262 int expected_add_ranges
;
1263 svn_merge_range_t expected_adds
[10];
1264 int expected_del_ranges
;
1265 svn_merge_range_t expected_dels
[10];
1267 /* Expected results for performing svn_rangelist_diff
1268 while ignoring differences in inheritability. */
1269 int expected_add_ranges_ignore_inheritance
;
1270 svn_merge_range_t expected_adds_ignore_inheritance
[10];
1271 int expected_del_ranges_ignore_inheritance
;
1272 svn_merge_range_t expected_dels_ignore_inheritance
[10];
1275 #define SIZE_OF_RANGE_DIFF_TEST_ARRAY 16
1276 /* The actual test data array.
1278 'from' --> {"/A: 1,5-8", "/A: 1,6,10-12", <-- 'to'
1279 Number of adds when --> 1, { { 9, 12, TRUE } },
1280 considering inheritance
1282 Number of dels when --> 2, { { 4, 5, TRUE }, { 6, 8, TRUE } },
1283 considering inheritance
1285 Number of adds when --> 1, { { 9, 12, TRUE } },
1286 ignoring inheritance
1288 Number of dels when --> 2, { { 4, 5, TRUE }, { 6, 8, TRUE } } },
1289 ignoring inheritance
1291 The expected svn_merge_range_t's
1293 struct rangelist_diff_test_data test_data
[SIZE_OF_RANGE_DIFF_TEST_ARRAY
] =
1295 /* Add and Delete */
1297 1, { { 2, 3, TRUE
} },
1298 1, { { 0, 1, TRUE
} },
1299 1, { { 2, 3, TRUE
} },
1300 1, { { 0, 1, TRUE
} } },
1303 {"/A: 1", "/A: 1,3",
1304 1, { { 2, 3, TRUE
} },
1305 0, { { 0, 0, FALSE
} },
1306 1, { { 2, 3, TRUE
} },
1307 0, { { 0, 0, FALSE
} } },
1310 {"/A: 1,3", "/A: 1",
1311 0, { { 0, 0, FALSE
} },
1312 1, { { 2, 3, TRUE
} },
1313 0, { { 0, 0, FALSE
} },
1314 1, { { 2, 3, TRUE
} } },
1317 {"/A: 1,3", "/A: 1,3",
1318 0, { { 0, 0, FALSE
} },
1319 0, { { 0, 0, FALSE
} },
1320 0, { { 0, 0, FALSE
} },
1321 0, { { 0, 0, FALSE
} } },
1323 {"/A: 1,3*", "/A: 1,3*",
1324 0, { { 0, 0, FALSE
} },
1325 0, { { 0, 0, FALSE
} },
1326 0, { { 0, 0, FALSE
} },
1327 0, { { 0, 0, FALSE
} } },
1329 /* Adds and Deletes */
1330 {"/A: 1,5-8", "/A: 1,6,10-12",
1331 1, { { 9, 12, TRUE
} },
1332 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} },
1333 1, { { 9, 12, TRUE
} },
1334 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} } },
1337 1, { { 5, 6, TRUE
} },
1338 1, { { 5, 6, FALSE
} },
1339 0, { { 0, 0, FALSE
} },
1340 0, { { 0, 0, FALSE
} } },
1342 /* Intersecting range with different inheritability */
1344 1, { { 5, 6, FALSE
} },
1345 1, { { 5, 6, TRUE
} },
1346 0, { { 0, 0, FALSE
} },
1347 0, { { 0, 0, FALSE
} } },
1350 1, { { 5, 6, TRUE
} },
1351 1, { { 5, 6, FALSE
} },
1352 0, { { 0, 0, FALSE
} },
1353 0, { { 0, 0, FALSE
} } },
1355 {"/A: 1,5-8", "/A: 1,6*,10-12",
1356 2, { { 5, 6, FALSE
}, { 9, 12, TRUE
} },
1357 1, { { 4, 8, TRUE
} },
1358 1, { { 9, 12, TRUE
} },
1359 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} } },
1361 {"/A: 1,5-8*", "/A: 1,6,10-12",
1362 2, { { 5, 6, TRUE
}, { 9, 12, TRUE
} },
1363 1, { { 4, 8, FALSE
} },
1364 1, { { 9, 12, TRUE
} },
1365 2, { { 4, 5, FALSE
}, { 6, 8, FALSE
} } },
1367 /* Empty range diffs */
1369 0, { { 0, 0, FALSE
} },
1370 1, { { 2, 9, TRUE
} },
1371 0, { { 0, 0, FALSE
} },
1372 1, { { 2, 9, TRUE
} } },
1375 0, { { 0, 0, FALSE
} },
1376 1, { { 2, 9, FALSE
} },
1377 0, { { 0, 0, FALSE
} },
1378 1, { { 2, 9, FALSE
} } },
1381 1, { { 2, 9, TRUE
} },
1382 0, { { 0, 0, FALSE
} },
1383 1, { { 2, 9, TRUE
} },
1384 0, { { 0, 0, FALSE
} } },
1387 1, { { 2, 9, FALSE
} },
1388 0, { { 0, 0, FALSE
} },
1389 1, { { 2, 9, FALSE
} },
1390 0, { { 0, 0, FALSE
} } },
1392 /* Empty range no diff */
1394 0, { { 0, 0, FALSE
} },
1395 0, { { 0, 0, FALSE
} },
1396 0, { { 0, 0, FALSE
} },
1397 0, { { 0, 0, FALSE
} } },
1400 *msg
= "diff of rangelists";
1402 return SVN_NO_ERROR
;
1404 err
= child_err
= SVN_NO_ERROR
;
1405 for (i
= 0; i
< SIZE_OF_RANGE_DIFF_TEST_ARRAY
; i
++)
1407 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).to
, pool
));
1408 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).from
, pool
));
1409 to
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
1410 from
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
1412 /* Represent empty mergeinfo with an empty rangelist. */
1414 to
= apr_array_make(pool
, 0, sizeof(*to
));
1416 from
= apr_array_make(pool
, 0, sizeof(*from
));
1418 /* First diff the ranges while considering
1419 differences in inheritance. */
1420 SVN_ERR(svn_rangelist_diff(&deleted
, &added
, from
, to
, TRUE
, pool
));
1422 child_err
= verify_ranges_match(added
,
1423 (test_data
[i
]).expected_adds
,
1424 (test_data
[i
]).expected_add_ranges
,
1426 "svn_rangelist_diff"
1430 child_err
= verify_ranges_match(deleted
,
1431 (test_data
[i
]).expected_dels
,
1432 (test_data
[i
]).expected_del_ranges
,
1434 "svn_rangelist_diff"
1439 /* Now do the diff while ignoring differences in inheritance. */
1440 SVN_ERR(svn_rangelist_diff(&deleted
, &added
, from
, to
, FALSE
,
1442 child_err
= verify_ranges_match(
1444 (test_data
[i
]).expected_adds_ignore_inheritance
,
1445 (test_data
[i
]).expected_add_ranges_ignore_inheritance
,
1446 apr_psprintf(pool
, "svn_rangelist_diff case %i", i
),
1450 child_err
= verify_ranges_match(
1452 (test_data
[i
]).expected_dels_ignore_inheritance
,
1453 (test_data
[i
]).expected_del_ranges_ignore_inheritance
,
1454 apr_psprintf(pool
, "svn_rangelist_diff case %i", i
),
1458 /* Collect all the errors rather than returning on the first. */
1462 svn_error_compose(err
, child_err
);
1470 /* The test table. */
1472 struct svn_test_descriptor_t test_funcs
[] =
1475 SVN_TEST_PASS(test_parse_single_line_mergeinfo
),
1476 SVN_TEST_PASS(test_mergeinfo_dup
),
1477 SVN_TEST_PASS(test_parse_combine_rangeinfo
),
1478 SVN_TEST_PASS(test_parse_broken_mergeinfo
),
1479 SVN_TEST_PASS(test_remove_rangelist
),
1480 SVN_TEST_PASS(test_rangelist_remove_randomly
),
1481 SVN_TEST_PASS(test_remove_mergeinfo
),
1482 SVN_TEST_PASS(test_rangelist_reverse
),
1483 SVN_TEST_PASS(test_rangelist_intersect
),
1484 SVN_TEST_PASS(test_rangelist_intersect_randomly
),
1485 SVN_TEST_PASS(test_diff_mergeinfo
),
1486 SVN_TEST_PASS(test_merge_mergeinfo
),
1487 SVN_TEST_PASS(test_mergeinfo_intersect
),
1488 SVN_TEST_PASS(test_rangelist_to_string
),
1489 SVN_TEST_PASS(test_mergeinfo_to_string
),
1490 SVN_TEST_PASS(test_rangelist_merge
),
1491 SVN_TEST_PASS(test_rangelist_diff
),