コード例 #1
0
    def test_delete_overlaping_ranges_revered(self):
        """
        Same opperations as previous test, but order of branches is reversed
        (B now before A)
        """
        s = '0123456789'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # construct branch A, which deletes all but the first three
        # and last three characters.
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=4, val=2))
        A0.set_id('1A')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=3, val=2))
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('sd', [], offset=2, val=2))
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == '0189'

        # Branch B has common parent with A. It deletes all but '89'

        # User saw '0123456789' and deleted '3456'
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=3, val=4)
        B0.add_op(opB0)
        B0.set_id('0B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index > b_index
        assert doc.get_snapshot() == '0189'

        # User saw '012789' and deleted '27'
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=2, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '0189'

        # Delete Range not known by branch A
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=1, val=2)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == '09'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A2, B2])
        C.add_op(Op('si', [], offset=1, val='12345678'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == '0123456789'
コード例 #2
0
    def test_initial_dependency(self):
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        assert doc.get_open_changeset() == None
        assert doc.get_ordered_changesets() == [doc.get_root_changeset()]

        assert doc.get_dependencies() == [doc.get_root_changeset()]
コード例 #3
0
    def test_delete_overlaping_ranges2_reversed(self):
        """
        Same opperations as previous test, but order of branches is reversed
        (B now before A)
        """
        s = '0123456789TARGET'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # branch deletes the '234567' in three ops.
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=4, val=2))
        A0.set_id('1A0')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=3, val=2))
        A1.set_id('A1')
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('sd', [], offset=2, val=2))
        A2.set_id('A2')
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == '0189TARGET'

        # Branch B has common parent with A. It deletes all but
        # 'TARGET' in three ops.

        # User Saw '0123456789TARGET', deleted '234', which branch A
        # already did.
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=2, val=3)
        B0.add_op(opB0)
        B0.set_id('0B0')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index > b_index
        assert doc.get_snapshot() == '0189TARGET'

        # User Saw '0156789TARGET', deleted '567', which branch A
        # already did.
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=2, val=3)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '0189TARGET'

        # User Saw '0189TARGET', deleted '0189', which branch A has
        # NOT done.
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=0, val=4)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == 'TARGET'
コード例 #4
0
    def test_two_deletes_in_first_branch_reverse(self):
        """
        Same opperations as previous test, but order of branches is reversed
        (B now before A)
        """
        s = 'ab123cd456gh789ik'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=7, val=2))
        A0.set_id('1A')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=10, val=3))
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('si', [], offset=7, val='ef'))
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == 'ab123cdef6ghik'

        # Branch B has common parent with A. First it deletes a
        # partialy overlaping range in A
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=8, val=2)
        B0.add_op(opB0)
        B0.set_id('0B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index > b_index
        assert doc.get_snapshot() == 'ab123cdefghik'

        # Delete range partially overlaping range in A
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=10, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == 'ab123cdefghik'

        # Delete Range unaffected by branch A
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=2, val=3)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == 'abcdefghik'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A2, B2])
        C.add_op(Op('si', [], offset=9, val='j'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == 'abcdefghijk'
コード例 #5
0
    def test_two_deletes_in_first_branch(self):
        """  01234567890123456 (helpful index of characters in doc)"""
        s = 'ab123cd456gh789ik'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # construct branch A, which has two string deletes, then
        # adds text
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=7, val=2))
        A0.set_id('A')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=10, val=3))
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('si', [], offset=7, val='ef'))
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == 'ab123cdef6ghik'

        # Branch B has common parent with A. First it deletes a
        # partialy overlaping range in A
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=8, val=2)
        B0.add_op(opB0)
        B0.set_id('B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index < b_index
        assert doc.get_snapshot() == 'ab123cdefghik'

        # Delete range partially overlaping range in A
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=10, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == 'ab123cdefghik'

        # Delete Range unaffected by branch A
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=2, val=3)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == 'abcdefghik'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A2, B2])
        C.add_op(Op('si', [], offset=9, val='j'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == 'abcdefghijk'
コード例 #6
0
    def test_multiple_dependencies(self):
        """
             -- B ---- E
            /         /
        root -- A -- D
            \       /
             -- C --
        """
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        B = Changeset(doc.get_id(), "user0", [root])
        B.set_id('b')
        doc.receive_changeset(B)

        A = Changeset(doc.get_id(), "user1", [root])
        A.set_id('a')
        doc.receive_changeset(A)
        assert set(doc.get_dependencies()) == set([B,A])
        assert doc.get_ordered_changesets() == [root, A, B]

        C = Changeset(doc.get_id(), "user2", [root])
        C.set_id('c')
        doc.receive_changeset(C)
        assert set(doc.get_dependencies()) == set([B,A,C])
        assert doc.get_ordered_changesets() == [root, A, B, C]
        assert doc.get_ordered_changesets() == doc.tree_to_list()


        # test_multiple_dependencies_common_base
        D = Changeset(doc.get_id(), "user0", [C,A])
        D.set_id('d')
        doc.receive_changeset(D)
        assert set(doc.get_dependencies()) == set([B,D])
        assert doc.get_ordered_changesets() == [root, A, B, C, D]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        E = Changeset(doc.get_id(), 'user1', [B, D])
        E.set_id('e')
        doc.receive_changeset(E)
        assert doc.get_dependencies() == [E]
        assert doc.get_ordered_changesets() == [root, A, B, C, D, E]
        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #7
0
    def test_one_delete_in_first_branch(self):
        """
        There is one delete in the first branch, multiple in branch B, then
        each has more string inserts.
        """
        doc = Document(snapshot='123abcde789')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # construct branch A, which begins with a string delete, then
        # adds text
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=3, val=5))
        A0.set_id('A')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('si', [], offset=3, val='456'))
        doc.receive_changeset(A1)
        assert doc.get_snapshot() == '123456789'

        # Branch B has common parent with A. B has three deletes, some of which
        # overlap the delete in branch A
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=4, val=2)
        B0.add_op(opB0)
        B0.set_id('B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index < b_index
        assert doc.get_snapshot() == '123456789'

        # Partially overlaping delete
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=6, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '1234569'

        # Delete Range unaffected by branch A
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=1, val=1)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == '134569'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A1, B2])
        C.add_op(Op('si', [], offset=1, val='2'))
        C.add_op(Op('si', [], offset=6, val='78'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == '123456789'
コード例 #8
0
    def test_overlaping_deletes_then_string_insert_reversed(self):
        """
        Same test as the previous one, except the order of the branches is
        reversed.
        """
        s = 'ZZZZZZZAAAAAAAAAAAAAAAAAAAAAAAAAXXXXX'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=0, val=32))
        A0.add_op(Op('si', [], offset=0, val='T'))
        A0.set_id('2')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('si', [], offset=1, val="h"))
        A1.add_op(Op('si', [], offset=2, val="e"))
        A1.add_op(Op('si', [], offset=3, val=" "))
        A1.set_id('A1')
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('si', [], offset=4, val="Q"))
        A2.add_op(Op('si', [], offset=5, val="u"))
        A2.add_op(Op('si', [], offset=6, val="i"))
        A2.set_id('A2')
        doc.receive_changeset(A2)

        A3 = Changeset(doc.get_id(), 'u1', [A2])
        A3.add_op(Op('si', [], offset=7, val="c"))
        A3.add_op(Op('si', [], offset=8, val="k"))
        A3.add_op(Op('si', [], offset=9, val=" "))
        A3.set_id('A3')
        doc.receive_changeset(A3)
        assert doc.get_snapshot() == 'The Quick XXXXX'

        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=7, val=30)
        B0.add_op(opB0)
        B0.set_id('1')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index > b_index
        assert doc.get_snapshot() == 'The Quick '

        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('si', [], offset=7, val='Brown Fox.')
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == 'Brown Fox.The Quick '
コード例 #9
0
    def test_random_changesets(self):
        """
        Create a bunch of changesets with random dependencies, add them
        all to the doc, and make sure the resulting order is the same
        as when done with tree_to_list().
        """
        # NOTE: Testing large numbers of changesets is slow, so dropping
        # the number for normal testing.

        # NUMBER_OF_CHANGESETS = 5000
        NUMBER_OF_CHANGESETS = 200

        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        assert doc.get_ordered_changesets() == doc.tree_to_list()
        i = 1
        while i < NUMBER_OF_CHANGESETS:
            i += 1
            doc, cs = add_random_changeset(doc)
            assert len(doc.get_ordered_changesets()) == i

        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #10
0
 def build_random_initial_document(self):
     snapshot = ''.join(random.sample(self.remaining_chars, 100))
     doc = Document(snapshot=snapshot)
     doc.get_ordered_changesets()[0].ops[0].cheat = ""
     for i, char in enumerate(snapshot):
         before = list(snapshot[:i])
         after = list(snapshot[i + 1:])
         self.results[char]['before'] = before
         self.results[char]['after'] = after
         self.remaining_chars = self.remaining_chars.replace(char, '')
     doc.HAS_EVENT_LOOP = False
     self.doc = doc
     return doc
コード例 #11
0
    def test_multiple_css_with_same_multiple_dependencies(self):
        """
        A -- B -- D--F -- G
              \    \/   /
               \   /\  /
                - C--E-
        Both F and E depend on D and C
        """
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        A = Changeset(doc.get_id(), "user0", [root])
        A.set_id('a')
        doc.receive_changeset(A)
        assert doc.get_ordered_changesets() == [root, A]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        B = Changeset(doc.get_id(), "user1", [A])
        B.set_id('b')
        doc.receive_changeset(B)
        assert doc.get_ordered_changesets() == [root, A, B]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        C = Changeset(doc.get_id(), "user3", [B])
        C.set_id('c')
        doc.receive_changeset(C)
        assert doc.get_ordered_changesets() == [root, A, B, C]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        D = Changeset(doc.get_id(), "user4", [B])
        D.set_id('d')
        doc.receive_changeset(D)
        assert doc.get_ordered_changesets() == [root, A, B, C, D]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        E = Changeset(doc.get_id(), "user5", [C, D])
        E.set_id('e')
        doc.receive_changeset(E)
        assert doc.get_ordered_changesets() == [root, A, B, C, D, E]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        F = Changeset(doc.get_id(), "user6", [C, D])
        F.set_id('f')
        doc.receive_changeset(F)
        assert set(doc.get_dependencies()) == set([E,F])
        assert doc.get_ordered_changesets() == [root, A,B,C,D,E,F]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        G = Changeset(doc.get_id(), "user5", [E,F])
        doc.receive_changeset(G)
        assert doc.get_dependencies() == [G]
        assert doc.get_ordered_changesets() == [root, A, B, C, D, E, F, G]
        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #12
0
    def test_missing_changesets(self):
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        assert doc.missing_changesets == set([])
        assert doc.pending_new_changesets == []
        
        root = doc.get_root_changeset()
        A = Changeset(doc.get_id(), "dummyuser", [root])
        doc.receive_changeset(A)
        assert doc.missing_changesets == set([])
        assert doc.pending_new_changesets == []

        # Just one Changeset gets put in pending list
        B = Changeset(doc.get_id(), "user1", ["C"])
        B.set_id("B")
        doc.receive_changeset(B)
        assert doc.get_ordered_changesets() == [root, A]
        assert doc.missing_changesets == set(["C"])
        assert doc.pending_new_changesets == [B]

        C = Changeset(doc.get_id(), "user1", [A])
        C.set_id("C")
        doc.receive_changeset(C)
        assert doc.missing_changesets == set([])
        assert doc.pending_new_changesets == []
        assert B.get_parents() == [C]
        assert doc.get_ordered_changesets() == [root, A, C, B]

        # Now a string of changesets put on pending list
        D = Changeset(doc.get_id(), "user1", ["G"])
        D.set_id("D")
        doc.receive_changeset(D)
        assert doc.missing_changesets == set(["G"])
        assert doc.pending_new_changesets == [D]
        assert doc.get_ordered_changesets() == [root, A, C, B]

        E = Changeset(doc.get_id(), "user1", ["D"])
        E.set_id("E")
        doc.receive_changeset(E)
        assert E.get_parents() == [D]
        assert doc.missing_changesets == set(["G"])
        assert doc.pending_new_changesets == [D, E]
        assert doc.get_ordered_changesets() == [root, A, C, B]

        F = Changeset(doc.get_id(), "user1", ["E"])
        F.set_id("F")
        doc.receive_changeset(F)
        assert doc.missing_changesets ==set( ["G"])
        assert doc.pending_new_changesets == [D, E, F]
        assert doc.get_ordered_changesets() == [root, A, C, B]

        G = Changeset(doc.get_id(), "user1", ["C"])
        G.set_id("G")
        doc.receive_changeset(G)
        assert doc.missing_changesets == set([])
        assert doc.pending_new_changesets == []
        assert doc.get_ordered_changesets() == [root, A, C, B, G, D, E, F]
        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #13
0
    def test_sequential_changeset(self):
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        cs0 = Changeset(doc.get_id(), "dummyuser", [root])
        rid = root.get_id()
        assert doc.receive_changeset(cs0)
        assert rid == doc.get_root_changeset().get_id()
        assert root.get_children() == [cs0]
        assert doc.get_dependencies() == [cs0]
        assert doc.get_ordered_changesets() == [root, cs0]


        cs1 = Changeset(doc.get_id(), "user1", [cs0])
        assert doc.receive_changeset(cs1)
        assert doc.get_ordered_changesets() == [root, cs0, cs1]
        assert doc.get_dependencies() == [cs1]

        cs2 = Changeset(doc.get_id(), "user1", [cs1])
        assert doc.receive_changeset(cs2)
        assert doc.get_ordered_changesets() == [root, cs0, cs1, cs2]
        assert doc.get_dependencies() == [cs2]
        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #14
0
    def test_one_delete_in_first_branch_reversed(self):
        """
        Same opperations as previous test, but order of branches is reversed
        (B now before A)
        """
        doc = Document(snapshot='123abcde789')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=3, val=5))
        A0.set_id('1A')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('si', [], offset=3, val='456'))
        doc.receive_changeset(A1)

        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=4, val=2)
        B0.add_op(opB0)
        B0.set_id('0B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index > b_index
        assert doc.get_snapshot() == '123456789'

        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=6, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '1234569'

        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=1, val=1)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == '134569'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A1, B2])
        C.add_op(Op('si', [], offset=1, val='2'))
        C.add_op(Op('si', [], offset=6, val='78'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == '123456789'
コード例 #15
0
    def test_random(self):
        """
        Randomly insert the changsets into new documents.
        """
        NUMBER_OF_ITERATIONS = 40

        iteration = 0
        while iteration < NUMBER_OF_ITERATIONS:
            doc = Document(snapshot='0123456789')
            self.create_changesets(doc)
            css = [self.A1, self.A0,
                   self.B1, self.B0,
                   self.C1, self.C0]
            while css:
                cs = random.choice(css)
                doc.receive_changeset(cs)
                css.remove(cs)
                # this document will not pull automaticly. flip a coin to see
                # if it should be pulled on this loop
                if random.random() > .5:
                    doc.pull_from_pending_list()
            # pull any remaining changesets from pending list
            doc.pull_from_pending_list()

            # This is the base of the resulting document. Then build up the A's
            # B's and C's.
            result = '01289'
            for cs in doc.get_ordered_changesets():
                if cs is self.A1:
                    result += 'AAAAA'
                elif cs is self.B1:
                    result += 'BBBBB'
                elif cs is self.C1:
                    result += 'CCCCC'
            assert doc.get_snapshot() == result
            iteration += 1
コード例 #16
0
    def test_complex_tree(self):
        """
        Some complex tree.
        
               C -- G -- H -------- K
              /         /            \
        A -- B -- D -- F -- J -- L -- M--
                   \       /
                    E --- I

        Should be:
        A B C G H K D E I J L M
        """
        
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        A = Changeset(doc.get_id(), "user0", [root])
        A.set_id('A')
        doc.receive_changeset(A)
        
        B = Changeset(doc.get_id(),"user1",[A])
        B.set_id('b')
        doc.receive_changeset(B)
        
        C = Changeset(doc.get_id(),"user3",[B])
        C.set_id('c')
        doc.receive_changeset(C)

        D = Changeset(doc.get_id(),"user4",[B])
        D.set_id('d')
        doc.receive_changeset(D)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]

        E = Changeset(doc.get_id(),"user5",[D])
        E.set_id('e')
        doc.receive_changeset(E)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]
        assert E.get_unaccounted_changesets() == [C]

        F = Changeset(doc.get_id(),"user6",[D])
        F.set_id('f')
        doc.receive_changeset(F)
        assert doc.get_ordered_changesets() == [root,A,B,C,D,E,F]

        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]
        assert E.get_unaccounted_changesets() == [C]
        assert F.get_unaccounted_changesets() == [C,E]

        G = Changeset(doc.get_id(),"user5",[C])
        G.set_id('g')
        doc.receive_changeset(G)
        # just a reminder of order now
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,F]

        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E]

        H = Changeset(doc.get_id(),"user5",[G,F])
        H.set_id('h')
        doc.receive_changeset(H)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,F,H]

        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E]

        I = Changeset(doc.get_id(),"user6",[E])
        I.set_id('i')
        doc.receive_changeset(I)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H]

        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E,I]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E,I]
        assert I.get_unaccounted_changesets() == [C,G]

        J = Changeset(doc.get_id(),"user5",[I,F])
        J.set_id('j')
        doc.receive_changeset(J)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,J]

        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E,I]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E,I]
        assert I.get_unaccounted_changesets() == [C,G]
        assert J.get_unaccounted_changesets() == [C,G,H]

        K = Changeset(doc.get_id(),"user5",[H])
        K.set_id('k')
        doc.receive_changeset(K)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J]

        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E,I]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E,I]
        assert I.get_unaccounted_changesets() == [C,G]
        assert J.get_unaccounted_changesets() == [C,G,H,K]
        assert K.get_unaccounted_changesets() == [E,I]

        L = Changeset(doc.get_id(),"user5",[J])
        L.set_id('l')
        doc.receive_changeset(L)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J,L]

        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E,I]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E,I]
        assert I.get_unaccounted_changesets() == [C,G]
        assert J.get_unaccounted_changesets() == [C,G,H,K]
        assert K.get_unaccounted_changesets() == [E,I]
        assert L.get_unaccounted_changesets() == [C,G,H,K]

        M = Changeset(doc.get_id(),"user5",[K,L])
        M.set_id('m')
        doc.receive_changeset(M)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J,L,M]

        assert D.get_unaccounted_changesets() == [C,G]
        assert E.get_unaccounted_changesets() == [C,G]
        assert F.get_unaccounted_changesets() == [C,G,E,I]
        assert G.get_unaccounted_changesets() == []
        assert H.get_unaccounted_changesets() == [E,I]
        assert I.get_unaccounted_changesets() == [C,G]
        assert J.get_unaccounted_changesets() == [C,G,H,K]
        assert K.get_unaccounted_changesets() == [E,I]
        assert L.get_unaccounted_changesets() == [C,G,H,K]
        assert M.get_unaccounted_changesets() == []
コード例 #17
0
    def test_complex_tree(self):
        """
        Some complex tree.

               C -- G -- H -------- K
              /         /            \
        A -- B -- D -- F -- J -- L -- M--
                   \       /
                    E --- I

        Should be:
        A B C G D E I F H K J L M
        """

        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        A = Changeset(doc.get_id(), "user0", [root])
        A.set_id('A')
        doc.receive_changeset(A)
        assert doc.get_ordered_changesets() == [root, A]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        B = Changeset(doc.get_id(),"user1",[A])
        B.set_id('b')
        doc.receive_changeset(B)
        assert doc.get_ordered_changesets() == [root,A,B]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        C = Changeset(doc.get_id(),"user3",[B])
        C.set_id('c')
        doc.receive_changeset(C)
        assert doc.get_ordered_changesets() == [root,A,B,C]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        D = Changeset(doc.get_id(),"user4",[B])
        D.set_id('d')
        doc.receive_changeset(D)
        assert doc.get_ordered_changesets() == [root,A,B,C,D]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        E = Changeset(doc.get_id(),"user5",[D])
        E.set_id('e')
        doc.receive_changeset(E)
        assert doc.get_ordered_changesets() == [root,A,B,C,D,E]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        F = Changeset(doc.get_id(),"user6",[D])
        F.set_id('f')
        doc.receive_changeset(F)
        assert doc.get_ordered_changesets() == [root,A,B,C,D,E,F]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        G = Changeset(doc.get_id(),"user5",[C])
        G.set_id('g')
        doc.receive_changeset(G)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,F]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        H = Changeset(doc.get_id(),"user5",[G,F])
        H.set_id('h')
        doc.receive_changeset(H)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,F,H]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        I = Changeset(doc.get_id(),"user6",[E])
        I.set_id('i')
        doc.receive_changeset(I)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        J = Changeset(doc.get_id(),"user5",[I,F])
        J.set_id('j')
        doc.receive_changeset(J)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,J]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        K = Changeset(doc.get_id(),"user5",[H])
        K.set_id('k')
        doc.receive_changeset(K)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        L = Changeset(doc.get_id(),"user5",[J])
        L.set_id('l')
        doc.receive_changeset(L)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J,L]
        assert doc.get_ordered_changesets() == doc.tree_to_list()

        M = Changeset(doc.get_id(),"user5",[K,L])
        M.set_id('m')
        doc.receive_changeset(M)
        assert doc.get_ordered_changesets() == [root,A,B,C,G,D,E,I,F,H,K,J,L,M]
        assert doc.get_ordered_changesets() == doc.tree_to_list()
コード例 #18
0
    def test_overlaping_deletes_then_string_insert(self):
        """
        Both branches delete all the A's from the document. Additionally, one
        branch deletes all the Z's, the other all the X's. Then one inserts
        'The Quick ', the other branch 'Brown Fox.' Each uses several ops to
        achieve this.

        NOTE: This example is slightly convoluted and hard to follow. The test
        is only here because it was a reproducable failure that had no solution
        at the time.
        """
        s = 'ZZZZZZZAAAAAAAAAAAAAAAAAAAAAAAAAXXXXX'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=0, val=32))
        A0.add_op(Op('si', [], offset=0, val='T'))
        A0.set_id('A0')
        doc.receive_changeset(A0)

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('si', [], offset=1, val="h"))
        A1.add_op(Op('si', [], offset=2, val="e"))
        A1.add_op(Op('si', [], offset=3, val=" "))
        A1.set_id('A1')
        doc.receive_changeset(A1)

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('si', [], offset=4, val="Q"))
        A2.add_op(Op('si', [], offset=5, val="u"))
        A2.add_op(Op('si', [], offset=6, val="i"))
        A2.set_id('A2')
        doc.receive_changeset(A2)

        A3 = Changeset(doc.get_id(), 'u1', [A2])
        A3.add_op(Op('si', [], offset=7, val="c"))
        A3.add_op(Op('si', [], offset=8, val="k"))
        A3.add_op(Op('si', [], offset=9, val=" "))
        A3.set_id('A3')
        doc.receive_changeset(A3)
        assert doc.get_snapshot() == 'The Quick XXXXX'

        # Branch B has common parent with A. It saw the original document and
        # deleted everything but the Y's
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=7, val=30)
        B0.add_op(opB0)
        B0.set_id('B0')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index < b_index
        assert doc.get_snapshot() == 'The Quick '

        # User B saw only the Y's and inserted text at the end.
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('si', [], offset=7, val='Brown Fox.')
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == 'The Quick Brown Fox.'
コード例 #19
0
    def test_multiple_css_with_same_multiple_dependencies(self):
        """
          A1        D1
         /         /
        A -- B -- D--F -- G
              \    \/   /
               \   /\  /
                - C--E-
        Both F and E depend on D and C
        """
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()
        A = Changeset(doc.get_id(), "user0", [root])
        A.set_id('a')
        doc.receive_changeset(A)
        
        B = Changeset(doc.get_id(), "user1", [A])
        B.set_id('b')
        doc.receive_changeset(B)
        
        C = Changeset(doc.get_id(), "user3", [B])
        C.set_id('c')
        doc.receive_changeset(C)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []

        D = Changeset(doc.get_id(), "user4", [B])
        D.set_id('d')
        doc.receive_changeset(D)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]

        E = Changeset(doc.get_id(), "user5", [C, D])
        E.set_id('e')
        doc.receive_changeset(E)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]
        assert E.get_unaccounted_changesets() == []

        
        F = Changeset(doc.get_id(), "user6", [C, D])
        F.set_id('f')
        doc.receive_changeset(F)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == []
        assert C.get_unaccounted_changesets() == []
        assert D.get_unaccounted_changesets() == [C]
        assert E.get_unaccounted_changesets() == []
        assert F.get_unaccounted_changesets() == [E]

        A1 = Changeset(doc.get_id(), "user5", [A])
        A1.set_id('1a')
        doc.receive_changeset(A1)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == [A1]
        assert C.get_unaccounted_changesets() == [A1]
        assert D.get_unaccounted_changesets() == [A1,C]
        assert E.get_unaccounted_changesets() == [A1]
        assert F.get_unaccounted_changesets() == [A1,E]
        assert A1.get_unaccounted_changesets() == []

        D1 = Changeset(doc.get_id(), "user5", [D])
        D1.set_id('1d')
        doc.receive_changeset(D1)
        assert doc.get_ordered_changesets() == [root, A,A1,B,C,D,D1,E,F]
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == [A1]
        assert C.get_unaccounted_changesets() == [A1]
        assert D.get_unaccounted_changesets() == [A1,C]
        assert E.get_unaccounted_changesets() == [A1,D1]
        assert F.get_unaccounted_changesets() == [A1,D1,E]
        assert A1.get_unaccounted_changesets() == []
        assert D1.get_unaccounted_changesets() == [A1,C]

        G = Changeset(doc.get_id(), "user5", [E,F])
        doc.receive_changeset(G)
        assert A.get_unaccounted_changesets() == []
        assert B.get_unaccounted_changesets() == [A1]
        assert C.get_unaccounted_changesets() == [A1]
        assert D.get_unaccounted_changesets() == [A1,C]
        assert E.get_unaccounted_changesets() == [A1,D1]
        assert F.get_unaccounted_changesets() == [A1,D1,E]
        assert A1.get_unaccounted_changesets() == []
        assert D1.get_unaccounted_changesets() == [A1,C]
        assert G.get_unaccounted_changesets() == [A1,D1]
コード例 #20
0
    def test_delete_overlaping_ranges2(self):
        """
        Branch A and B independently delete the same characters in the middle
        of the string using different combinations of opperations. Then they
        perform other string operations that need to keep synced.
        """
        s = '0123456789TARGET'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # branch deletes the '234567' in three ops.
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=4, val=2))
        A0.set_id('A0')
        doc.receive_changeset(A0)
        assert doc.get_snapshot() == '01236789TARGET'

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=3, val=2))
        A1.set_id('A1')
        doc.receive_changeset(A1)
        assert doc.get_snapshot() == '012789TARGET'

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('sd', [], offset=2, val=2))
        A2.set_id('A2')
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == '0189TARGET'

        # Branch B has common parent with A. It deletes all but
        # 'TARGET' in three ops.

        # User Saw '0123456789TARGET', deleted '234', which branch A
        # already did.
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=2, val=3)
        B0.add_op(opB0)
        B0.set_id('B0')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index < b_index
        assert doc.get_snapshot() == '0189TARGET'

        # User Saw '0156789TARGET', deleted '567', which branch A
        # already did.
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=2, val=3)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '0189TARGET'

        # User Saw '0189TARGET', deleted '0189', which branch A has
        # NOT done.
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=0, val=4)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == 'TARGET'
コード例 #21
0
    def test_delete_overlaping_ranges(self):
        """
        Branch A and B independently delete the same characters in the middle
        of the string using different combinations of opperations. Then they
        perform other string operations that need to keep synced.
        """
        s = '0123456789'
        doc = Document(snapshot=s)
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # construct branch A, which deletes all but the first three
        # and last three characters.
        A0 = Changeset(doc.get_id(), 'u1', [root])
        A0.add_op(Op('sd', [], offset=4, val=2))
        A0.set_id('A')
        doc.receive_changeset(A0)
        assert doc.get_snapshot() == '01236789'

        A1 = Changeset(doc.get_id(), 'u1', [A0])
        A1.add_op(Op('sd', [], offset=3, val=2))
        doc.receive_changeset(A1)
        assert doc.get_snapshot() == '012789'

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('sd', [], offset=2, val=2))
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == '0189'

        # Branch B has common parent with A. It deletes all but '89'

        # User saw '0123456789' and deleted '3456', which was already
        # deleted in branch A.
        B0 = Changeset(doc.get_id(), 'u2', [root])
        opB0 = Op('sd', [], offset=3, val=4)
        B0.add_op(opB0)
        B0.set_id('B')
        doc.receive_changeset(B0)
        a_index = doc.get_ordered_changesets().index(A0)
        b_index = doc.get_ordered_changesets().index(B0)
        assert a_index < b_index
        assert doc.get_snapshot() == '0189'

        # User saw '012789' and deleted '27', which was already
        # deleted in branch A.
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        opB1 = Op('sd', [], offset=2, val=2)
        B1.add_op(opB1)
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == '0189'

        # Delete Range not known by branch A
        B2 = Changeset(doc.get_id(), 'u2', [B1])
        opB2 = Op('sd', [], offset=1, val=2)
        B2.add_op(opB2)
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == '09'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A2, B2])
        C.add_op(Op('si', [], offset=1, val='12345678'))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == '0123456789'