2
# Author: Tim Cole <tim.cole@canonical.com>
4
# Copyright 2009 Canonical Ltd.
6
# This program is free software: you can redistribute it and/or modify it
7
# under the terms of the GNU General Public License version 3, as published
8
# by the Free Software Foundation.
10
# This program is distributed in the hope that it will be useful, but
11
# WITHOUT ANY WARRANTY; without even the implied warranties of
12
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
13
# PURPOSE. See the GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License along
16
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
"""Tests for tree merging."""
21
from unittest import TestCase
22
from ubuntuone.u1sync.genericmerge import MergeNode, generic_merge
23
from ubuntuone.u1sync.merge import (
24
merge_trees, ClobberLocalMerge, ClobberServerMerge, SyncMerge)
25
from ubuntuone.storageprotocol.dircontent_pb2 import FILE, DIRECTORY
28
def accumulate_path(nodes, name, partial_parent):
29
"""pre-merge which accumulates a path"""
30
return os.path.join(partial_parent, name)
32
def capture_merge(nodes, partial_result, child_results):
33
"""post-merge which accumulates merge results."""
34
return (nodes, partial_result, child_results)
37
class MergeTest(TestCase):
38
"""Tests for generic tree merges."""
40
def test_generic_merge(self):
41
"""Tests that generic merge behaves as expected."""
42
tree_a = MergeNode(DIRECTORY, children={
43
'foo': MergeNode(FILE, uuid=uuid.uuid4()),
44
'bar': MergeNode(FILE, uuid=uuid.uuid4()),
46
tree_b = MergeNode(DIRECTORY, children={
47
'bar': MergeNode(FILE, uuid=uuid.uuid4()),
48
'baz': MergeNode(FILE, uuid=uuid.uuid4()),
50
result = generic_merge(trees=[tree_a, tree_b],
51
pre_merge=accumulate_path,
52
post_merge=capture_merge,
53
partial_parent="", name="ex")
54
expected_result = ([tree_a, tree_b], "ex", {
55
'foo': ([tree_a.children['foo'], None], "ex/foo", {}),
56
'bar': ([tree_a.children['bar'], tree_b.children['bar']],
58
'baz': ([None, tree_b.children['baz']], "ex/baz", {}),
60
self.assertEqual(expected_result, result)
62
def test_clobber(self):
63
"""Tests clobbering merges."""
64
server_tree = MergeNode(DIRECTORY, children={
65
'foo': MergeNode(FILE, content_hash="dummy:abc"),
66
'bar': MergeNode(FILE, content_hash="dummy:xyz"),
67
'baz': MergeNode(FILE, content_hash="dummy:aaa"),
69
local_tree = MergeNode(DIRECTORY, children={
70
'foo': MergeNode(FILE, content_hash="dummy:cde"),
71
'bar': MergeNode(FILE, content_hash="dummy:zyx"),
72
'hoge': MergeNode(FILE, content_hash="dummy:bbb"),
74
result_tree = merge_trees(local_tree, local_tree,
75
server_tree, server_tree,
77
self.assertEqual(local_tree, result_tree)
78
result_tree = merge_trees(local_tree, local_tree,
79
server_tree, server_tree,
81
self.assertEqual(server_tree, result_tree)
84
"""Test sync merges."""
85
server_tree = MergeNode(DIRECTORY, children={
86
'bar': MergeNode(FILE, content_hash="dummy:xyz"),
87
'baz': MergeNode(FILE, content_hash="dummy:aaa"),
88
'foo': MergeNode(FILE, content_hash="dummy:abc"),
90
old_server_tree = MergeNode(DIRECTORY, children={})
91
local_tree = MergeNode(DIRECTORY, children={
92
'bar': MergeNode(FILE, content_hash="dummy:xyz"),
93
'foo': MergeNode(FILE, content_hash="dummy:abc"),
94
'hoge': MergeNode(FILE, content_hash="dummy:bbb"),
96
old_local_tree = MergeNode(DIRECTORY, children={})
97
expected_tree = MergeNode(DIRECTORY, children={
98
'bar': MergeNode(FILE, content_hash="dummy:xyz"),
99
'baz': MergeNode(FILE, content_hash="dummy:aaa"),
100
'foo': MergeNode(FILE, content_hash="dummy:abc"),
101
'hoge': MergeNode(FILE, content_hash="dummy:bbb"),
103
result_tree = merge_trees(old_local_tree, local_tree,
104
old_server_tree, server_tree,
106
self.assertEqual(result_tree, expected_tree)