コード例 #1
0
    def test_array_insert(self):
        doc0 = Document()
        doc0.snapshot.set_snapshot([])
        doc1 = self.doc1
        doc2 = self.doc2

        # whole doc is just an empty array. alter it
        op1 = Op('ai', [], val=['c'], offset=0)
        doc0.apply_op(op1)
        assert doc0.get_snapshot() == ['c']
        # insert at start
        op2 = Op('ai', [], val=['a'], offset=0)
        doc0.apply_op(op2)
        assert doc0.get_snapshot() == ['a', 'c']
        # insert at end
        op3 = Op('ai', [], val=['d'], offset=2)
        doc0.apply_op(op3)
        assert doc0.get_snapshot() == ['a', 'c', 'd']
        # insert several in the middle
        op4 = Op('ai', [], val=['b0', 'b1', 'b2'], offset=1)
        doc0.apply_op(op4)
        assert doc0.get_snapshot() == ['a', 'b0', 'b1', 'b2', 'c', 'd']

        # insert into some array deep in doc
        op5 = Op('ai', [3, 1], val=['a'], offset=1)
        doc2.apply_op(op5)
        assert doc2.get_value([3, 1]) == ['dimen', 'a']

        # again
        op6 = Op('ai', ['fifth'], val=['a'], offset=1)
        doc1.apply_op(op6)
        result6 = [55, 'a', 66, {'sixth': 'deep string'}, 'rw']
        assert doc1.get_value(['fifth']) == result6
コード例 #2
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'
コード例 #3
0
    def test_boolean_negation(self):
        doc0 = Document()
        doc0.snapshot.set_snapshot(False)
        doc1 = self.doc1
        doc2 = self.doc2

        # whole document is a boolean. Just change that
        op1 = Op('bn', [])
        doc0.apply_op(op1)
        assert doc0.get_snapshot() is True
        doc0.apply_op(op1)
        assert doc0.get_snapshot() is False

        # boolean at some key/index
        op2 = Op('bn', [4])
        doc2.apply_op(op2)
        assert doc2.get_value([4]) == False
        doc2.apply_op(op2)
        assert doc2.get_value([4]) == True

        # boolean along some path
        path3 = ['fifth',2,'sixth']
        doc1.apply_op(Op('set', path3, val=True))
        op3 = Op('bn', path3)
        doc1.apply_op(op3)
        assert doc1.get_value(path3) == False
        doc1.apply_op(op3)
        assert doc1.get_value(path3) == True
コード例 #4
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'
コード例 #5
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'
コード例 #6
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'
コード例 #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_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'
コード例 #10
0
def test_overlaping_deletes(delete_index, single_first):
    original_snapshot = 'abcdefghijklmnopqrstuvwxyz'
    doc = Document(snapshot=original_snapshot)
    doc.HAS_EVENT_LOOP = False

    z_index = 14
    if delete_index >= 5 and delete_index < 15:
        z_index = 15
    if delete_index == 25:
        z_index = 15

    single_id = 'A' if single_first else 'B'
    range_id = 'B' if single_first else 'A'

    css_data = [
        ('sd', delete_index, 1, ['root'], single_id),
        ('sd', 5, 10, ['root'], range_id),  # delete 'fghijklmno'
        ('si', z_index, 'Z', ['A', 'B'], 'C'),

        ('sd', 10, 10, ['root'], '0'),  # delete 'klmnopqrst'
    ]

    css = build_changesets_from_tuples(css_data, doc)

    for cs in css:
        doc.receive_changeset(cs)

    resulting_snapshot = 'abcdeuvwxyZz'
    l = original_snapshot[delete_index]
    resulting_snapshot = resulting_snapshot.replace(l, '')

    assert doc.get_snapshot() == resulting_snapshot
コード例 #11
0
    def test_array_delete(self):
        doc0 =  Document()
        doc0.snapshot.set_snapshot([])
        doc1 = self.doc1
        doc2 = self.doc2

        # can technically delete nothing from empty list. why not
        op1 = Op('ad', [], offset=0, val=0)
        doc0.apply_op(op1)
        assert doc0.get_snapshot() == []

        # remove one from list
        op2 = Op('ad', [], offset=1, val=1)
        doc2.apply_op(op2)
        assert doc2.get_value([1]) == 'normal, ol string'

        # from nested lists
        op3 = Op('ad', [2], offset=1, val=1)
        doc2.apply_op(op3)
        assert doc2.get_value([2]) == [['multi'],['array']]

        # delete multiple elements
        op4 = Op('ad', [], offset=0, val=4)
        doc2.apply_op(op4)
        assert doc2.get_snapshot() == [None, 42]

        # delete last in list:
        op5 = Op('ad', [], offset=1, val=1)
        doc2.apply_op(op5)
        assert doc2.get_snapshot() == [None]

        # in dicts
        op6 = Op('ad', ['fifth'], offset=2, val=2)
        doc1.apply_op(op6)
        assert doc1.get_value(['fifth']) == [55,66]
コード例 #12
0
    def test_move_in_root(self):
        doc = Document()
        doc.snapshot.set_snapshot('ABCDEFGHIJKLMNOPQRS')

        # move from higher index to lower
        op1 = Op('sm', [], offset=10, val=4, dest_path=[], dest_offset=2)
        doc.apply_op(op1)
        assert doc.get_snapshot() == 'ABKLMNCDEFGHIJOPQRS'

        # move from lower index to higher
        op2 = Op('sm', [], offset=2, val=4, dest_path=[], dest_offset=10)
        doc.apply_op(op2)
        assert doc.get_snapshot() == 'ABCDEFGHIJKLMNOPQRS'  # original value

        # move by one index
        op3 = Op('sm', [], offset=0, val=6, dest_path=[], dest_offset=1)
        doc.apply_op(op3)
        assert doc.get_snapshot() == 'GABCDEFHIJKLMNOPQRS'

        op4 = Op('sm', [], offset=10, val=9, dest_path=[], dest_offset=0)
        doc.apply_op(op4)
        assert doc.get_snapshot() == 'KLMNOPQRSGABCDEFHIJ'
コード例 #13
0
    def test_delete_in_second_branch(self):
        """
        """
        doc = Document(snapshot='abcdefghij')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

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

        # Branch B has common parent with A. It inserts strings at the end
        # which should not be deleted.
        B0 = Changeset(doc.get_id(), 'u2', [root])
        for i in xrange(10):
            op = Op('si', [], offset=10 + i, val=str(i))
            B0.add_op(op)
        B0.set_id('1B')
        doc.receive_changeset(B0)
        assert doc.get_snapshot() == 'abcde0123456789'
コード例 #14
0
def test_insert_within_many_overlaping_deletes():
    doc = Document(snapshot='abcdefghij')
    doc.HAS_EVENT_LOOP = False
    css_data = [
        ('si', 5, 'X', ['root'], 'A'),  # should result in abcdeXfghij
        ('sd', 4, 2, ['root'], 'B'),  # deletes 'ef'
        ('sd', 3, 4, ['root'], 'C'),  # deletes 'defg'
        ('si', 5, 'J', ['B', 'C'], 'D'),  # insert 'J' right before 'j'

        ('sd', 3, 4, ['root'], 'E')  # deletes 'defg'
    ]

    css = build_changesets_from_tuples(css_data, doc)

    for cs in css:
        doc.receive_changeset(cs)
    assert doc.get_snapshot() == 'abchiJj'
コード例 #15
0
    def test_number_add(self):
        doc0 =  Document()
        doc0.snapshot.set_snapshot(0)
        doc1 = self.doc1
        doc2 = self.doc2

        # whole document is just a number. Alter it.
        op1 = Op('na', [], val=5)
        doc0.apply_op(op1)
        assert doc0.get_snapshot() == 5

        # number deeper in doc
        op2 = Op('na', ['fifth',1], val=-100)
        doc1.apply_op(op2)
        assert doc1.get_value(['fifth',1]) == -34

        # funkier numbers accepted by JSON
        # int frac
        op3 = Op('na', ['fifth',1], val=34.5)
        doc1.apply_op(op3)
        assert doc1.get_value(['fifth',1]) == 0.5
コード例 #16
0
def test_insert_within_overlaping_deletes(insert_index, resulting_index,
                                          insert_first,
                                          low_index_in_0_branch):

    doc = Document(snapshot='abcdefghijklmnopqrstuvwxyz')
    doc.HAS_EVENT_LOOP = False

    first_delete_index = 10 if low_index_in_0_branch else 5
    zero_branch_index = 5 if low_index_in_0_branch else 10

    z_index = 16
    if insert_index > first_delete_index and \
       insert_index < first_delete_index + 10:
        z_index = 15
    if insert_index == 26:
        z_index = 15

    insert_id = 'A' if insert_first else 'B'
    delete_id = 'B' if insert_first else 'A'

    css_data = [
        ('si', insert_index, 'X', ['root'], insert_id),  # insert letter X
        ('sd', first_delete_index, 10, ['root'], delete_id),  # delete 'fghijklmno'
        ('si', z_index, 'Z', ['A', 'B'], 'C'),  # at a 'Z' right before the
                                                # existing 'z'

        ('sd', zero_branch_index, 10, ['root'], '0'),  # delete 'klmnopqrst'
    ]

    css = build_changesets_from_tuples(css_data, doc)

    for cs in css:
        doc.receive_changeset(cs)

    resulting_snapshot = 'abcdeuvwxyZz'
    if not resulting_index is None:
        rs = resulting_snapshot
        ri = resulting_index
        resulting_snapshot = rs[:ri] + 'X' + rs[ri:]
    assert doc.get_snapshot() == resulting_snapshot
コード例 #17
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
コード例 #18
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'
コード例 #19
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'
コード例 #20
0
    def test_partial_overlaping_deletes(self):
        """
        At the same time, two users delete the same text, then insert
        different text. The union of the deletion ranges should be
        deleted and the two sets of inserted text should appear in
        full, side by side.

        Note: This test is fairly redundant. Just don't want to delete an old
        test.
        """
        doc = Document(snapshot='')
        doc.HAS_EVENT_LOOP = False
        root = doc.get_root_changeset()

        # create a common parrent for two divergent branches
        common_parent = Changeset(doc.get_id(), 'u1', [root])
        common_parent.add_op(Op('si', [], offset=0, val='12345678'))
        doc.receive_changeset(common_parent)
        assert doc.get_snapshot() == '12345678'

        # construct branch A, which begins with a string delete, then
        # inserts 'abcde' in three changesets.
        A0 = Changeset(doc.get_id(), 'u1', [common_parent])
        A0.add_op(Op('sd', [], offset=5, val=3))
        A0.add_op(Op('si', [], offset=5, val='abc'))
        A0.set_id('A')
        doc.receive_changeset(A0)
        assert doc.get_snapshot() == '12345abc'

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

        A2 = Changeset(doc.get_id(), 'u1', [A1])
        A2.add_op(Op('si', [], offset=9, val='e'))
        doc.receive_changeset(A2)
        assert doc.get_snapshot() == '12345abcde'

        # Branch B has common parent with A. Insert some text at the
        # end, delete the same range branch A deleted, then insert
        # more text
        B0 = Changeset(doc.get_id(), 'u2', [common_parent])
        B0.add_op(Op('si', [], offset=8, val='f'))
        B0.set_id('B')
        doc.receive_changeset(B0)
        assert doc.get_snapshot() == '12345abcdef'

        # CS with overlapping delete range
        B1 = Changeset(doc.get_id(), 'u2', [B0])
        B1.add_op(Op('sd', [], offset=0, val=8))
        B1.add_op(Op('si', [], offset=1, val='g'))
        B1.add_op(Op('si', [], offset=2, val='hi'))
        B1.set_id('B1')
        doc.receive_changeset(B1)
        assert doc.get_snapshot() == 'abcdefghi'

        B2 = Changeset(doc.get_id(), 'u2', [B1])
        B2.add_op(Op('si', [], offset=4, val='jkl'))
        B2.set_id('B2')
        doc.receive_changeset(B2)
        assert doc.get_snapshot() == 'abcdefghijkl'

        # combine these braches again
        C = Changeset(doc.get_id(), 'u2', [A2, B2])
        C.add_op(Op('si', [], offset=6, val=' XYZ '))
        doc.receive_changeset(C)
        assert doc.get_snapshot() == 'abcdef XYZ ghijkl'
    def test_hazard_for_insert_with_future_overlapping_deletes(self):
        doc = Document(snapshot='WfjxUPBNyE')
        doc.HAS_EVENT_LOOP = False

        # Both dd8 and 64d delete the string '7j'. That overlap must be relayed
        # back to cs 98c.

        css_data = [
            ('si', 3, 'iu0I', ['root'], 'b3a'),  # Wfj iu0I xUPBNyE

            ('si', 12, 'p5Z', ['b3a'], '98c'),  # Wfjiu0IxUPBN p5Z yE
            ('sd', 1, 3, ['98c'], 'c3e'),  # delete fji
            ('si', 11, 'DRv', ['c3e'], '3c6'),  # Wu0IxUPBNp5 DRv ZyE
            ('si', 0, 'Tt9G', ['3c6'], 'bdd'),  # Tt9G Wu0IxUPBNp5DRvZyE
            ('si', 0, 'gkrY', ['bdd'], '44e'),  # gkrY Tt9GWu0IxUPBNp5DRvZyE
            ('si', 0, 'M', ['44e'], '79b'),  # M gkrYTt9GWu0IxUPBNp5DRvZyE

            ('si', 0, '7O', ['b3a'], 'fb7'),  # 7O Wfjiu0IxUPBNyE
            ('si', 14, 'ad', ['fb7'], '26f'),  # 7OWfjiu0IxUPBN ad yE
            ('si', 11, 'w8cK', ['26f'], '7c3'),  # 7OWfjiu0IxU w8cK PBNadyE
            ('si', 20, 'mb', ['7c3'], '810'),  # 7OWfjiu0IxUw8cKPBNad mb yE
            ('sd', 1, 3, ['810'], '254'),  # delete OWf

            ('si', 7, 'J1', ['254'], '39c'),  # 7jiu0Ix J1 Uw8cKPBNadmbyE
            ('sd', 19, 1, ['39c'], '4c6'),  # delete m
            ('si', 12, 'e4', ['4c6'], '44f'),  # 7jiu0IxJ1Uw8 e4 cKPBNadbyE
            ('si', 19, 'LV', ['44f'], 'b25'),  # 7jiu0IxJ1Uw8e4cKPBN LV adbyE
            ('sd', 0, 3, ['b25'], 'dd8'),  # delete 7ji
            ('si', 14, 'hH2s', ['dd8'], 'bac'),
            # u0IxJ1Uw8e4cKP hH2s BNLVadbyE

            ('sd', 0, 2, ['254'], '64d'),  # delete 7j

            ('si', 2, '6nA', ['bac', '64d'], '25f'),
            # u0 6nA IxJ1Uw8e4cKPhH2sBNLVadbyE
            ('sd', 7, 4, ['25f'], '35a'),
            # delete J1Uw
            ('si', 9, '3lSz', ['35a'], 'b0c'),
            # u06nAIx8e 3lSz 4cKPhH2sBNLVadbyE
            ('si', 21, 'CXqQ', ['b0c'], '017'),
            # u06nAIx8e3lSz4cKPhH2s CXqQ BNLVadbyE
            ('si', 26, 'Fo', ['017'], '68e'),
            # u06nAIx8e3lSz4cKPhH2sCXqQB Fo NLVadbyE

            ('sd', 23, 5, ['79b', '68e'], '895'),  # delete cKPhH
        ]

        self.css = build_changesets_from_tuples(css_data, doc)
        get_cs = self.get_cs

        for i in self.css[:7]:
            doc.receive_changeset(i)
        assert doc.get_snapshot() == 'MgkrYTt9GWu0IxUPBNp5DRvZyE'

        cs = get_cs('fb7')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7OWu0IxUPBNp5DRvZyE'

        cs = get_cs('26f')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7OWu0IxUPBNp5DRvZadyE'

        cs = get_cs('7c3')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7OWu0IxUw8cKPBNp5DRvZadyE'

        cs = get_cs('810')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7OWu0IxUw8cKPBNp5DRvZadmbyE'

        cs = get_cs('254')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7u0IxUw8cKPBNp5DRvZadmbyE'

        cs = get_cs('39c')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7u0IxJ1Uw8cKPBNp5DRvZadmbyE'

        cs = get_cs('4c6')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7u0IxJ1Uw8cKPBNp5DRvZadbyE'

        cs = get_cs('44f')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7u0IxJ1Uw8e4cKPBNp5DRvZadbyE'

        cs = get_cs('b25')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9G7u0IxJ1Uw8e4cKPBNp5DRvZLVadbyE'

        cs = get_cs('dd8')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'MgkrYTt9Gu0IxJ1Uw8e4cKPBNp5DRvZLVadbyE'

        cs = get_cs('bac')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu0IxJ1Uw8e4cKPhH2sBNp5DRvZLVadbyE'

        cs = get_cs('64d')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu0IxJ1Uw8e4cKPhH2sBNp5DRvZLVadbyE'

        cs = get_cs('25f')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIxJ1Uw8e4cKPhH2sBNp5DRvZLVadbyE'

        cs = get_cs('35a')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIx8e4cKPhH2sBNp5DRvZLVadbyE'

        cs = get_cs('b0c')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIx8e3lSz4cKPhH2sBNp5DRvZLVadbyE'

        cs = get_cs('017')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIx8e3lSz4cKPhH2sCXqQBNp5DRvZLVadbyE'

        cs = get_cs('68e')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIx8e3lSz4cKPhH2sCXqQBFoNp5DRvZLVadbyE'

        cs = get_cs('895')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'MgkrYTt9Gu06nAIx8e3lSz42sCXqQBFoNp5DRvZLVadbyE'
コード例 #22
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.'
    def test_hazard_for_insert_when_future_insert_is_deleted(self):
        doc = Document(snapshot="05IiYTALOC")
        doc.HAS_EVENT_LOOP = False

        css_data = [
            ("si", 8, "3Z", ["root"], "ba4"),  # 05IiYTAL 3Z OC
            ("si", 2, "XkGu", ["ba4"], "179"),  # 05 XkGu IiYTAL3ZOC
            ("si", 9, "Mpb", ["179"], "9b5"),  # 05XkGuIiY Mpb TAL3ZOC
            ("si", 18, "6wc2", ["9b5"], "133"),  # 05XkGuIiYMpbTAL3ZO 6wc2 C
            ("si", 4, "xUg", ["133"], "36f"),  # 05Xk xUg GuIiYMpbTAL3ZO6wc2C
            ("si", 4, "NdKa", ["36f"], "6ad"),
            # 05Xk NdKa xUgGuIiYMpbTAL3ZO6wc2C
            ("si", 15, "hE", ["6ad"], "ebe"),
            # 05XkNdKaxUgGuIi hE YMpbTAL3ZO6wc2C
            ("si", 23, "H7", ["ebe"], "2b6"),
            # 05XkNdKaxUgGuIihEYMpbTA H7 L3ZO6wc2C
            ("si", 34, "yD", ["2b6"], "c0c"),
            # 05XkNdKaxUgGuIihEYMpbTAH7L3ZO6wc2C yD
            ("sd", 5, 5, ["ba4"], "b31"),  # delete TAL3Z
            ("si", 4, "9R", ["b31"], "96a"),  # 05Ii 9R YOC
            ("sd", 2, 4, ["96a"], "74e"),  # delete Ii9R
            ("si", 1, "41", ["74e"], "2f0"),  # 0 41 5YOC
            ("si", 0, "oQmB", ["2f0"], "ffc"),  # oQmB 0415YOC
            ("sd", 2, 4, ["ffc"], "da8"),  # delete mB04
            ("si", 3, "rn", ["da8"], "36d"),  # oQ1 rn 5YOC
            ("si", 0, "qtWS", ["74e"], "d96"),  # qtWS 05YOC'
            ("si", 2, "Psj", ["d96"], "319"),  # qt Psj WS05YOC
            ("si", 6, "FV", ["319"], "20e"),  # qtPsjW FV S05YOC
            ("si", 9, "lJve", ["20e"], "5ef"),  # qtPsjWFVS lJve 05YOC
            ("si", 8, "zf8", ["5ef", "36d"], "c73"),  # oQ1rn5YO zf8 C
            ("sd", 29, 3, ["c0c", "c73"], "5f3"),
        ]

        self.css = build_changesets_from_tuples(css_data, doc)
        get_cs = self.get_cs

        doc.receive_changeset(self.css[0])
        assert doc.get_snapshot() == "05IiYTAL3ZOC"

        if True:
            cs = get_cs("179")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkGuIiYTAL3ZOC"

            cs = get_cs("9b5")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkGuIiYMpbTAL3ZOC"

            cs = get_cs("133")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkGuIiYMpbTAL3ZO6wc2C"

            cs = get_cs("36f")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkxUgGuIiYMpbTAL3ZO6wc2C"

            cs = get_cs("6ad")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkNdKaxUgGuIiYMpbTAL3ZO6wc2C"

            cs = get_cs("ebe")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkNdKaxUgGuIihEYMpbTAL3ZO6wc2C"

            cs = get_cs("2b6")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkNdKaxUgGuIihEYMpbTAH7L3ZO6wc2C"

            cs = get_cs("c0c")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "05XkNdKaxUgGuIihEYMpbTAH7L3ZO6wc2CyD"

        cs = get_cs("b31")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "05XkNdKaxUgGuIihEYMpbO6wc2CyD"

        cs = get_cs("96a")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "05XkNdKaxUgGuIihE9RYMpbO6wc2CyD"

        cs = get_cs("74e")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "05XkNdKaxUgGuYMpbO6wc2CyD"

        if True:
            cs = get_cs("2f0")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "0415XkNdKaxUgGuYMpbO6wc2CyD"

            cs = get_cs("ffc")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "oQmB0415XkNdKaxUgGuYMpbO6wc2CyD"

            cs = get_cs("da8")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "oQ15XkNdKaxUgGuYMpbO6wc2CyD"

            cs = get_cs("36d")
            doc.receive_changeset(cs)
            assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2CyD"

        cs = get_cs("d96")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2CyD"

        cs = get_cs("319")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2CyD"

        cs = get_cs("20e")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2CyD"

        cs = get_cs("5ef")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2CyD"

        cs = get_cs("c73")
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == "oQ1rn5XkNdKaxUgGuYMpbO6wc2zf8CyD"
コード例 #24
0
    def test_expand_deletion_range(self):
        doc = Document(snapshot='HjpRFtZXW5')
        doc.HAS_EVENT_LOOP = False

        css_data = [
            ('si', 7, 'OeI', ['root'], 'c3c'),  # HjpRFtZ OeI XW5
            ('sd', 2, 5, ['c3c'], '950'),  # delete pRFtZ
            ('si', 2, 'Qx', ['950'], 'bf0'),  # Hj Qx OeIXW5
            ('sd', 2, 4, ['bf0'], '4c5'),  # delete QxOe
            ('si', 6, 'U6', ['4c5'], '61a'),  # HjIXW5 U6
            ('si', 3, 'AG', ['61a'], '1f0'),  # HjI AG XW5U6

            ('si', 3, 'qwEg', ['1f0'], '393'),  # HjI qwEg AGXW5U6
            ('si', 9, 'vsY', ['393'], '18d'),  # HjIqwEgAG vsY XW5U6
            ('si', 0, 'MiNV', ['18d'], '688'),  # MiNV HjIqwEgAGvsYXW5U6
            ('si', 20, 'L4n', ['688'], '796'),  # MiNVHjIqwEgAGvsYXW5U L4n 6
            ('si', 5, '9l', ['796'], 'b29'),  # MiNVH 9l jIqwEgAGvsYXW5UL4n6
            ('si', 1, 'k0Jf', ['b29'], 'e1a'),
            # M k0Jf iNVH9ljIqwEgAGvsYXW5UL4n6

            ('si', 8, 'd', ['e1a'], 'a23'),
            # Mk0JfiNV d H9ljIqwEgAGvsYXW5UL4n6

            ('sd', 3, 1, ['1f0'], '47a'),  # delete A
            ('sd', 0, 3, ['47a'], 'cc0'),  # delete HjI
            ('si', 4, 'K1DT', ['cc0'], 'd32'),  # GXW5 K1DT U6
            ('si', 5, 'b3oS', ['d32'], '175'),  # GXW5K b3oS 1DTU6
            ('si', 3, 'hm8z', ['175'], 'd28'),  # GXW hm8z 5Kb3oS1DTU6

            ('sd', 0, 5, ['1f0'], '997'),  # delete HjIAG
            ('si', 0, 'rBya', ['997'], '17a'),  # rBya XW5U6
            ('sd', 7, 1, ['17a'], '592'),  # delete U
            ('si', 8, 'cPu', ['592'], '893'),  # rByaXW56 cPu
            ('si', 1, 'C72', ['d28', '893'], 'b20'),
            # r C72 ByaXWhm8z5Kb3oS1DT6cPu

            ('sd', 37, 3, ['a23', 'b20'], '9e0'),  # delete 6cP
        ]

        self.css = build_changesets_from_tuples(css_data, doc)
        get_cs = self.get_cs

        for i in self.css[:13]:
            doc.receive_changeset(i)
        assert doc.get_snapshot() == 'Mk0JfiNVdH9ljIqwEgAGvsYXW5UL4n6'

        for i in self.css[13:18]:
            doc.receive_changeset(i)
        assert doc.get_snapshot() == 'Mk0JfiNVdqwEgGvsYXWhm8z5Kb3oS1DTUL4n6'

        cs = get_cs('997')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'Mk0JfiNVdvsYXWhm8z5Kb3oS1DTUL4n6'

        cs = get_cs('17a')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'Mk0JfiNVdvsYrByaXWhm8z5Kb3oS1DTUL4n6'

        cs = get_cs('592')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'Mk0JfiNVdvsYrByaXWhm8z5Kb3oS1DTL4n6'

        cs = get_cs('893')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'Mk0JfiNVdvsYrByaXWhm8z5Kb3oS1DTL4n6cPu'

        cs = get_cs('b20')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == \
            'Mk0JfiNVdvsYrC72ByaXWhm8z5Kb3oS1DTL4n6cPu'

        cs = get_cs('9e0')
        doc.receive_changeset(cs)
        assert doc.get_snapshot() == 'Mk0JfiNVdvsYrC72ByaXWhm8z5Kb3oS1DTL4nu'