Ejemplo n.º 1
0
async def test_get_last_event(get_ds, datastore_cls, timestamp):
    ds = await get_ds(datastore_cls)
    async with ds.connection() as conn:
        cds = await create_conv(conn, ds)
        pid = await cds.add_component(
            Components.PARTICIPANTS,
            address='*****@*****.**',
            permissions=perms.FULL,
        )
        action = Action('*****@*****.**', '123', Verbs.ADD, Components.MESSAGES, item='msg_id', timestamp=timestamp)
        action.participant_id, action.perm = pid, perms.FULL
        await cds.save_event('event_1', action)

        event_id, event_timestamp = await cds.get_item_last_event(Components.MESSAGES, 'msg_id')
        assert event_id == 'event_1'
        assert event_timestamp == timestamp

        # go 1, 3, 2 to make sure we're ordering on the commit sequence not event_id
        await cds.save_event('event_3', action)

        event_id, event_timestamp = await cds.get_item_last_event(Components.MESSAGES, 'msg_id')
        assert event_id == 'event_3'
        assert event_timestamp == timestamp

        await cds.save_event('event_2', action)

        event_id, event_timestamp = await cds.get_item_last_event(Components.MESSAGES, 'msg_id')
        assert event_id == 'event_2'
        assert event_timestamp == timestamp

        with pytest.raises(EventNotFound):
            await cds.get_item_last_event(Components.PARTICIPANTS, 'foobar')
Ejemplo n.º 2
0
async def test_publish_invalid_args(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    with pytest.raises(BadDataException) as excinfo:
        await controller.act(a, foo='bar')
    assert excinfo.value.args[0] == "Conversations.add_remote: missing a required argument: 'data'"
    assert len(controller.ds.data) == 0
Ejemplo n.º 3
0
async def test_publish_conversation_two_messages_wrong_id(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    data = deepcopy(correct_data)
    data['messages'][0]['id'] = 'id1'
    data['messages'].extend([
        {
            'author': '*****@*****.**',
            'body': 'the second body',
            'id': 'id2',
            'parent': 'id1',
            'timestamp': datetime.datetime(2016, 1, 2),
        },
        {
            'author': '*****@*****.**',
            'body': 'the third body',
            'id': 'id3',
            'parent': 'foobar',
            'timestamp': datetime.datetime(2016, 1, 3),
        }
    ])
    with pytest.raises(ComponentNotFound) as excinfo:
        await controller.act(a, data=data)
    assert excinfo.value.args[0] == 'message foobar not found'
Ejemplo n.º 4
0
async def test_publish_conversation_two_messages(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    data = deepcopy(correct_data)
    data['messages'].append(
        {
            'author': '*****@*****.**',
            'body': 'the second body',
            'id': 'different_id',
            'parent': 'd21625d617b1e8eb8989aa3d57a5aae691f9ed2a',
            'timestamp': datetime.datetime(2016, 1, 2),
        }
    )
    await controller.act(a, data=data)

    assert len(ds.data) == 1
    assert ds.data[0]['conv_id'] == conv_id
    assert ds.data[0]['subject'] == 'the subject'
    assert len(ds.data[0]['messages']) == 2
    messages = list(ds.data[0]['messages'].values())
    assert messages[0]['body'] == 'the body'
    assert messages[1]['body'] == 'the second body'
    assert ds.data[0]['timestamp'] == datetime.datetime(2016, 1, 2)
    assert len(ds.data[0]['participants']) == 2
Ejemplo n.º 5
0
async def test_publish_misshaped_data(controller, data, exc):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    with pytest.raises(BadDataException) as excinfo:
        await controller.act(a, data=data)
    assert exc == excinfo.value.args[0]
    assert len(controller.ds.data) == 0
Ejemplo n.º 6
0
async def test_publish_no_timestamp(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=None)
    a.event_id = a.calc_event_id()
    with pytest.raises(BadDataException) as excinfo:
        await controller.act(a, data=deepcopy(correct_data))
    assert excinfo.value.args[0] == 'remote actions should always have a timestamp'
    assert len(controller.ds.data) == 0
Ejemplo n.º 7
0
async def test_wrong_hash(controller):
    w_conv_id = conv_id + '+wrong'
    a = Action('*****@*****.**', w_conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    with pytest.raises(BadHash) as excinfo:
        await controller.act(a, data=deepcopy(correct_data))
    assert excinfo.value.args[0] == 'provided hash {} does not match computed hash {}'.format(w_conv_id, conv_id)
    assert len(controller.ds.data) == 0
Ejemplo n.º 8
0
async def test_publish_conversation_wrong_message_id(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    data = deepcopy(correct_data)
    data['messages'][0]['parent'] = 'not None'
    with pytest.raises(MisshapedDataException) as excinfo:
        await controller.act(a, data=data)
    assert excinfo.value.args[0] == 'first message parent should be None'
Ejemplo n.º 9
0
async def test_lock_edit(conversation):
    ds, ctrl, conv_id = await conversation()
    msg1_id = list(ds.data[0]['messages'])[0]
    assert len(ds.data[0]['events']) == 1
    peid = ds.data[0]['events'][0]['id']
    a = Action('*****@*****.**', conv_id, Verbs.LOCK, Components.MESSAGES, item=msg1_id, parent_event_id=peid)
    await ctrl.act(a)
    peid = a.calc_event_id()
    a = Action('*****@*****.**', conv_id, Verbs.EDIT, Components.MESSAGES, item=msg1_id, parent_event_id=peid)
    with pytest.raises(ComponentLocked) as excinfo:
        await ctrl.act(a, body='hi, how are you again?')
    assert 'ComponentLocked: messages with id = {} locked'.format(msg1_id) in str(excinfo)
Ejemplo n.º 10
0
async def test_publish_simple_conversation(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, Components.CONVERSATIONS, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    await controller.act(a, data=deepcopy(correct_data))

    assert len(ds.data) == 1
    assert ds.data[0]['conv_id'] == conv_id
    assert ds.data[0]['subject'] == 'the subject'
    assert len(ds.data[0]['messages']) == 1
    assert list(ds.data[0]['messages'].values())[0]['body'] == 'the body'
    assert ds.data[0]['timestamp'] == datetime.datetime(2016, 1, 2)
    assert len(ds.data[0]['participants']) == 2
Ejemplo n.º 11
0
async def test_publish_reply_bad_ts(two_controllers):
    ctrl1, ctrl2, conv_id = await two_controllers()

    assert (len(ctrl1.ds.data), len(ctrl2.ds.data)) == (1, 0)
    a = Action('*****@*****.**', conv_id, Verbs.PUBLISH, Components.CONVERSATIONS)
    await ctrl1.act(a)
    assert (len(ctrl1.ds.data), len(ctrl2.ds.data)) == (1, 1)

    conv_id = ctrl1.ds.data[0]['conv_id']
    msg1_id = list(ctrl2.ds.data[0]['messages'])[0]
    a = Action('*****@*****.**', conv_id, Verbs.ADD, Components.MESSAGES, timestamp=datetime_tz(year=2000))
    a.event_id = a.calc_event_id()
    with pytest.raises(BadDataException) as excinfo:
        await ctrl1.act(a, parent_id=msg1_id, body='this is a reply')
    assert excinfo.value.args[0] == 'timestamp not after parent timestamp: 2000-01-01 00:00:00+00:00'
Ejemplo n.º 12
0
async def test_missing_conversation(client):
    ts = datetime.now()
    action2 = Action('*****@*****.**', '123', Verbs.ADD, Components.MESSAGES, timestamp=ts)
    data = {
        'address': '*****@*****.**',
        'timestamp': ts,
        'event_id': action2.calc_event_id(),
        'kwargs': {
            'parent_id': '123',
            'body': 'reply',
        }
    }
    r = await client.post('/123/messages/add/', data=encoding.encode(data), headers=AUTH_HEADER)
    assert r.status == 400
    content = await r.read()
    assert content == b'ConversationNotFound: conversation 123 not found\n'
Ejemplo n.º 13
0
async def test_lock_unlock_message(conversation):
    ds, ctrl, conv_id = await conversation()
    conv = ds.data[0]
    assert len(conv['messages']) == 1
    msg1_id = list(conv['messages'])[0]
    peid = ds.data[0]['events'][0]['id']
    a = Action('*****@*****.**', conv_id, Verbs.LOCK, Components.MESSAGES, item=msg1_id, parent_event_id=peid)
    await ctrl.act(a)
    peid = a.calc_event_id()
    assert len(conv['locked']) == 1
    locked_v = list(conv['locked'])[0]
    assert locked_v == 'messages:{}'.format(msg1_id)

    a = Action('*****@*****.**', conv_id, Verbs.UNLOCK, Components.MESSAGES, item=msg1_id, parent_event_id=peid)
    await ctrl.act(a)
    assert len(conv['locked']) == 0
Ejemplo n.º 14
0
async def test_publish_conversation_two_messages_repeat_id(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    data = deepcopy(correct_data)
    data['messages'].append(
        {
            'author': '*****@*****.**',
            'body': 'the second body',
            'id': 'd21625d617b1e8eb8989aa3d57a5aae691f9ed2a',
            'parent': 'd21625d617b1e8eb8989aa3d57a5aae691f9ed2a',
            'timestamp': datetime.datetime(2016, 1, 2),
        }
    )
    with pytest.raises(BadDataException) as excinfo:
        await controller.act(a, data=data)
    assert excinfo.value.args[0] == 'message id d21625d617b1e8eb8989aa3d57a5aae691f9ed2a already exists'
Ejemplo n.º 15
0
async def test_publish_conversation_two_messages_wrong_timestamp(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = a.calc_event_id()
    ds = controller.ds
    assert len(ds.data) == 0
    data = deepcopy(correct_data)
    data['messages'].extend([
        {
            'author': '*****@*****.**',
            'body': 'the second body',
            'id': 'id2',
            'parent': 'd21625d617b1e8eb8989aa3d57a5aae691f9ed2a',
            'timestamp': datetime.datetime(2015, 1, 1),
        },
    ])
    with pytest.raises(BadDataException) as excinfo:
        await controller.act(a, data=data)
    assert excinfo.value.args[0] == 'timestamp 2015-01-01 00:00:00 not after parent'
Ejemplo n.º 16
0
async def test_add_message(client):
    action = Action('*****@*****.**', None, Verbs.ADD)
    conv_id = await client.em2_ctrl.act(action, subject='foo bar', body='hi, how are you?')
    conv_ds = client.em2_ctrl.ds.new_conv_ds(conv_id, None)
    msg1_id = list(conv_ds.conv_obj['messages'])[0]
    ts = action.timestamp + timedelta(seconds=1)
    action2 = Action('*****@*****.**', conv_id, Verbs.ADD, Components.MESSAGES, timestamp=ts)
    data = {
        'address': '*****@*****.**',
        'timestamp': ts,
        'event_id': action2.calc_event_id(),
        'kwargs': {
            'parent_id': msg1_id,
            'body': 'reply',
        }
    }
    r = await client.post('/{}/messages/add/'.format(conv_id), data=encoding.encode(data), headers=AUTH_HEADER)
    assert r.status == 201
    assert await r.text() == '\n'
Ejemplo n.º 17
0
async def test_edit_message_successful(conversation):
    ds, ctrl, conv_id = await conversation()
    a = Action('*****@*****.**', conv_id, Verbs.ADD, Components.PARTICIPANTS)
    await ctrl.act(a, address='*****@*****.**', permissions=perms.WRITE)

    conv = ds.data[0]
    msg1_id = list(conv['messages'])[0]
    a = Action('*****@*****.**', conv_id, Verbs.ADD, Components.MESSAGES)
    await ctrl.act(a, parent_id=msg1_id, body='reply')
    # have to do after act so timestamp is set
    parent_event_id = a.calc_event_id()

    msg2_id = None
    for msg2_id, info in conv['messages'].items():
        if info['parent'] == msg1_id:
            break
    assert conv['messages'][msg2_id]['body'] == 'reply'

    a = Action('*****@*****.**', conv_id, Verbs.EDIT, Components.MESSAGES, item=msg2_id,
               parent_event_id=parent_event_id)
    await ctrl.act(a, body='changed message')
    assert conv['messages'][msg2_id]['body'] == 'changed message'
Ejemplo n.º 18
0
async def test_save_event(get_ds, datastore_cls, timestamp):
    ds = await get_ds(datastore_cls)
    async with ds.connection() as conn:
        cds = await create_conv(conn, ds)
        pid = await cds.add_component(
            Components.PARTICIPANTS,
            address='*****@*****.**',
            permissions=perms.FULL,
        )
        action = Action('*****@*****.**', '123', Verbs.ADD, Components.PARTICIPANTS, item=pid, timestamp=timestamp)
        action.participant_id, action.perm = pid, perms.FULL
        await cds.save_event('event_1', action)

        await cds.save_event('event_2', action, value='foobar')

        # FIXME currently there are no api methods for returning updates and it's therefore not possible to check
        # these actions are saved correctly

        # NOTE: action action.conv_id is ignored in save_event and the cds conv_id is used instead
        cds2 = ds.new_conv_ds('bad', conn)
        action.participant_id, action.perm = pid, perms.FULL
        with pytest.raises(ConversationNotFound):
            await cds2.save_event('event_3', action)
Ejemplo n.º 19
0
async def test_publish_wrong_event_id(controller):
    a = Action('*****@*****.**', conv_id, Verbs.ADD, timestamp=timestamp)
    a.event_id = 'foobar'
    with pytest.raises(BadHash) as excinfo:
        await controller.act(a, data=deepcopy(correct_data))
    assert excinfo.value.args[0] == 'event_id "foobar" incorrect'