# # # patch "ChangeLog" # from [0b55b182e4bb56af32f85b11f62305cba6b4333a] # to [9191385e3a531e086d180834d3e2e5eb49db056d] # # patch "roster.cc" # from [4547e72b235da17471b9781c3416e7eac2904027] # to [53fa86f25f6c972e36ae212a85597212a85dd5ab] # # patch "roster.hh" # from [0f6d33d17d3d1c804be21f2e8025d86e47f087f9] # to [e066e66795e21670af3208b907e34702abf4b59e] # # patch "roster_merge.cc" # from [5a17827e8f84c0c8576f01e79c225a48b27c5505] # to [55b176100c4317bd25b35f9bba172e576eb7698a] # ============================================================ --- ChangeLog 0b55b182e4bb56af32f85b11f62305cba6b4333a +++ ChangeLog 9191385e3a531e086d180834d3e2e5eb49db056d @@ -1,3 +1,10 @@ +2006-02-19 Nathaniel Smith + + * roster.{hh,cc} (testing_node_id_source): Make this node source + available to unit tests in other files. + * roster_merge.cc (test_roster_merge_node_lifecycle): New test. + Still quite ugly. + 2006-02-18 Nathaniel Smith * roster_merge.cc (roster_merge): Remove obsolete FIXME. ============================================================ --- roster.cc 4547e72b235da17471b9781c3416e7eac2904027 +++ roster.cc 53fa86f25f6c972e36ae212a85597212a85dd5ab @@ -2877,19 +2877,18 @@ } }; -struct testing_node_id_source - : public node_id_source +testing_node_id_source() + : curr(first_node) +{} + +node_id +testing_node_id_source::next() { - testing_node_id_source() : curr(first_node) {} - virtual node_id next() - { - // L(FL("creating node %x\n") % curr); - node_id n = curr++; - I(!temp_node(n)); - return n; - } - node_id curr; -}; + // L(FL("creating node %x\n") % curr); + node_id n = curr++; + I(!temp_node(n)); + return n; +} template <> void dump(int const & i, std::string & out) ============================================================ --- roster.hh 0f6d33d17d3d1c804be21f2e8025d86e47f087f9 +++ roster.hh e066e66795e21670af3208b907e34702abf4b59e @@ -343,5 +343,17 @@ write_manifest_of_roster(roster_t const & ros, data & dat); +#ifdef BUILD_UNIT_TESTS + +struct testing_node_id_source + : public node_id_source +{ + testing_node_id_source(); + virtual node_id next(); + node_id curr; +}; + +#endif // BUILD_UNIT_TESTS + #endif ============================================================ --- roster_merge.cc 5a17827e8f84c0c8576f01e79c225a48b27c5505 +++ roster_merge.cc 55b176100c4317bd25b35f9bba172e576eb7698a @@ -547,7 +547,12 @@ // same in both, diff marks // different, left wins with 1 mark // different, right wins with 1 mark -// different, conflict +// different, conflict with 1 mark +// different, left wins with 2 marks +// different, right wins with 2 marks +// different, conflict with 1 mark winning, 1 mark losing +// different, conflict with 2 marks both conflicting +// // for: // node name, name and parent, file and dir // file content @@ -570,10 +575,122 @@ // between-node name conflict + both nodes orphaned // between-node name conflict + both nodes cause loop +// need roster, marking, birth revs, and uncommon ancestors for each side... + +namespace +{ + const revision_id a_uncommon1 = revision_id(std::string("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")); + const revision_id a_uncommon2 = revision_id(std::string("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")); + const revision_id b_uncommon1 = revision_id(std::string("cccccccccccccccccccccccccccccccccccccccc")); + const revision_id b_uncommon2 = revision_id(std::string("dddddddddddddddddddddddddddddddddddddddd")); + const revision_id common1 = revision_id(std::string("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee")); + const revision_id common2 = revision_id(std::string("ffffffffffffffffffffffffffffffffffffffff")); + + const file_id fid1 = file_id(std::string("1111111111111111111111111111111111111111")); + const file_id fid2 = file_id(std::string("2222222222222222222222222222222222222222")); + + split_path + split(std::string const & s) + { + split_path sp; + file_path_internal(s).split(sp); + return sp; + } +} + +static void +make_dir(roster_t & r, marking_map & markings, + revision_id const & birth_rid, revision_id const & parent_name_rid, + std::string const & name, node_id nid) +{ + r.create_dir_node(nid); + r.attach_node(nid, split(name)); + marking_t marking; + marking.birth_revision = birth_rid; + marking.parent_name.insert(parent_name_rid); + safe_insert(markings, std::make_pair(nid, marking)); +} + +static void +make_file(roster_t & r, marking_map & markings, + revision_id const & birth_rid, revision_id const & parent_name_rid, + revision_id const & file_content_rid, + std::string const & name, file_id const & content, + node_id nid) +{ + r.create_file_node(content, nid); + r.attach_node(nid, split(name)); + marking_t marking; + marking.birth_revision = birth_rid; + marking.parent_name.insert(parent_name_rid); + marking.contain.file_content.insert(file_content_rid); + safe_insert(markings, std::make_pair(nid, marking)); +} + +static void +make_lifecycle_objs(roster_t & r, marking_map & markings, revision_id uncommon, + std::string const & name, node_id common_dir_nid, node_id common_file_nid, + node_id & safe_dir_nid, node_id & safe_file_nid, node_id_source & nis) +{ + make_dir(r, markings, common1, common1, name + "_old_dir", common_dir_nid); + make_file(r, markings, common1, common1, name + "_old_file", common_file_nid); + safe_dir_nid = nis.next(); + make_dir(r, markings, uncommon, uncommon, name + "_safe_dir", safe_dir_nid); + safe_file_nid = nis.next(); + make_file(r, markings, uncommon, uncommon, uncommon, name + "_safe_file", fid1, safe_file_nid); + make_dir(r, markings, common1, common1, name + "_dead_dir", nis.next()); + make_file(r, markings, common1, common1, common1, name + "_dead_file", fid1, nis.next()); +} + + +static void +test_roster_merge_node_lifecycle() +{ + roster_t a_roster, b_roster; + marking_map a_markings, b_markings; + std::set a_uncommon, b_uncommon; + // boilerplate to get uncommon revision sets... + a_uncommon.insert(a_uncommon1); + a_uncommon.insert(a_uncommon2); + b_uncommon.insert(b_uncommon1); + b_uncommon.insert(b_uncommon2); + testing_node_id_source nis; + // boilerplate to set up a root node... + { + node_id root_nid = nis.next(); + make_dir(a_roster, a_markings, common1, common1, "", root_nid); + make_dir(b_roster, b_markings, common1, common1, "", root_nid); + } + // create some nodes on each side + node_id common_dir_nid = nis.next(); + node_id common_file_nid = nis.next(); + node_id a_safe_dir_nid, a_safe_file_nid, b_safe_dir_nid, b_safe_file_nid; + make_lifecycle_objs(a_roster, a_markings, a_uncommon1, "a", common_dir_nid, common_file_nid, + a_safe_dir_nid, a_safe_file_nid, nis); + make_lifecycle_objs(b_roster, b_markings, b_uncommon1, "b", common_dir_nid, common_file_nid, + b_safe_dir_nid, b_safe_file_nid, nis); + // do the merge + roster_merge_result result; + roster_merge(a_roster, a_markings, a_uncommon, b_roster, b_markings, b_uncommon, result); + I(result.clean()); + // 7 = 1 root + 2 common + 2 safe a + 2 safe b + I(result.roster.all_nodes().size() == 7); + // check that they're the right ones... + I(*result.roster.get_node(common_dir_nid) == *a_roster.get_node(common_dir_nid)); + I(*result.roster.get_node(common_file_nid) == *a_roster.get_node(common_file_nid)); + I(*result.roster.get_node(common_dir_nid) == *b_roster.get_node(common_dir_nid)); + I(*result.roster.get_node(common_file_nid) == *b_roster.get_node(common_file_nid)); + I(*result.roster.get_node(a_safe_dir_nid) == *a_roster.get_node(a_safe_dir_nid)); + I(*result.roster.get_node(a_safe_file_nid) == *a_roster.get_node(a_safe_file_nid)); + I(*result.roster.get_node(b_safe_dir_nid) == *b_roster.get_node(b_safe_dir_nid)); + I(*result.roster.get_node(b_safe_file_nid) == *b_roster.get_node(b_safe_file_nid)); +} + void add_roster_merge_tests(test_suite * suite) { I(suite); + suite->add(BOOST_TEST_CASE(&test_roster_merge_node_lifecycle)); } #endif // BUILD_UNIT_TESTS