Ejemplo n.º 1
0
async def test_post_date(mysql, mock_circlecore):
    mbox_id = uuid.uuid4()
    with MetaDataSession.begin():
        schema = Schema.create(display_name='Schema',
                               properties='date:datetime,id1:float')
        module = Module.create(display_name='Module')
        mbox = MessageBox(uuid=mbox_id,
                          schema_uuid=schema.uuid,
                          module_uuid=module.uuid)
        MetaDataSession.add(schema)
        MetaDataSession.add(module)
        MetaDataSession.add(mbox)

    envdir = mock_circlecore[1]
    database = Database(mysql.url, time_db_dir=envdir, log_dir=envdir)
    journal_writer = database.make_writer()
    queued_writer = journal_writer.child_writer
    run_loop = asyncio.ensure_future(journal_writer.run())

    # post
    message = ModuleMessage(mbox.uuid, 123456.789, 0, {
        'date': '2017-09-01T24:00:00Z',
        'id1': 3.14
    })
    await queued_writer.store(mbox, message)
    await queued_writer.flush()

    # close database
    await journal_writer.close()
    await run_loop

    with database._engine.begin() as connection:
        table = database.find_table_for_message_box(mbox)
        rows = connection.execute(select([table])).fetchall()
        assert len(rows) == 0
Ejemplo n.º 2
0
    def test_replication_link(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')

        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         display_name='Box')

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        replication_link = ReplicationLink.create(message_box_uuids=[box.uuid],
                                                  **_input)

        with MetaDataSession.begin():
            MetaDataSession.add(replication_link)

        replication_link = ReplicationLink.query.get(replication_link.uuid)
        assert isinstance(replication_link, ReplicationLink)
        assert replication_link.display_name == expected['display_name']
        assert replication_link.memo == expected['memo']
Ejemplo n.º 3
0
    def test_moge(self):
        """API認証"""
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema',
                                   properties='x:int,y:float,data:blob')
            module = Module.create(display_name='Module')
            mbox = MessageBox(uuid='4ffab839-cf56-478a-8614-6003a5980857',
                              schema_uuid=schema.uuid,
                              module_uuid=module.uuid)
            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        data_api_endpoint = self.get_url('/api/modules/{}/{}/data'.format(
            module.uuid, mbox.uuid))

        # 認証がいるよ
        response = self.fetch(data_api_endpoint)
        assert response.code == 403

        # 認証がいるよ
        response = self.fetch(
            data_api_endpoint,
            headers={'Authorization': 'Bearer {}'.format(user.encoded_token)})
        assert response.code == 200
Ejemplo n.º 4
0
    def test_message_box(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')

        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         **_input)

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        assert isinstance(box, MessageBox)
        assert box.display_name == expected['display_name']
        assert box.memo == expected['memo']

        assert isinstance(hash(box), int)
        assert isinstance(box.cc_uuid, uuid.UUID)

        jsonobj = box.to_json(with_schema=True, with_module=True)
        assert str(box.uuid) == jsonobj['uuid']
        assert box.display_name == jsonobj['displayName']
        assert box.memo == jsonobj['memo']
        assert str(box.module_uuid) == jsonobj['moduleUuid']
        assert str(box.schema_uuid) == jsonobj['schemaUuid']
        assert schema.display_name == jsonobj['schema']['displayName']
        assert module.display_name == jsonobj['module']['displayName']
Ejemplo n.º 5
0
    def test_rest(self):
        """登録されているModuleからのPOSTは404"""
        # make dummy environ
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema', properties='x:int,y:float')
            module = Module.create(display_name='Module')
            mbox = MessageBox(
                uuid='4ffab839-cf56-478a-8614-6003a5980856', schema_uuid=schema.uuid, module_uuid=module.uuid
            )
            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        response = self.fetch(
            self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
            method='POST',
            body=json.dumps({
                'x': 1,
                'y': 2.5
            }),
            headers={
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
            }
        )
        self.assertEqual(response.code, 200)
        self.datareceiver.receive_new_message.assert_called_once_with(str(mbox.uuid), {'x': 1, 'y': 2.5})
Ejemplo n.º 6
0
    async def on_master_migrate(self, message):
        assert self.state == ReplicationState.MIGRATING

        with MetaDataSession.begin():
            # save master info
            data = message['masterInfo']
            try:
                obj = CcInfo.query.filter_by(uuid=data['uuid']).one()
            except NoResultFound:
                obj = CcInfo(uuid=data['uuid'], myself=False)
            obj.update_from_json(data)
            obj.replication_master_id = self.master.id
            MetaDataSession.add(obj)

            master_info = obj

            self.master.master_uuid = master_info.uuid

            # migrate schemas
            for schema_uuid, data in message['schemas'].items():
                try:
                    obj = Schema.query.filter_by(uuid=data['uuid']).one()
                except NoResultFound:
                    obj = Schema(uuid=data['uuid'])
                obj.update_from_json(data)
                obj.cc_uuid = master_info.uuid
                MetaDataSession.add(obj)

            # migrate modules
            for module_uuid, data in message['modules'].items():
                try:
                    obj = Module.query.filter_by(uuid=data['uuid']).one()
                except NoResultFound:
                    obj = Module(uuid=data['uuid'])
                obj.update_from_json(data)
                obj.cc_uuid = master_info.uuid
                obj.replication_master_id = self.master.id
                MetaDataSession.add(obj)

            # migrate boxes
            self.target_boxes = {}
            for box_uuid, data in message['messageBoxes'].items():
                try:
                    obj = MessageBox.query.filter_by(uuid=data['uuid']).one()
                    if obj.schema_uuid != uuid.UUID(data['schemaUuid']):
                        raise DataConfilictedError('schemaUuid not match')
                    if obj.module_uuid != uuid.UUID(data['moduleUuid']):
                        raise DataConfilictedError('moduleUuid not match')
                except NoResultFound:
                    obj = MessageBox(
                        uuid=data['uuid'],
                        schema_uuid=data['schemaUuid'],
                        module_uuid=data['moduleUuid'],
                    )
                obj.update_from_json(data)
                MetaDataSession.add(obj)

                self.target_boxes[obj.uuid] = obj
Ejemplo n.º 7
0
    def test_check_match(self, _input, data, expected, mock_circlecore):
        jsonobj = dict(displayName='Schema', memo='memo', properties=_input)
        schema = Schema.create()
        schema.update_from_json(jsonobj)

        with MetaDataSession.begin():
            MetaDataSession.add(schema)

        schema = Schema.query.get(schema.uuid)
        ok, msg = schema.check_match(data)
        assert ok is expected
Ejemplo n.º 8
0
def _post_schemas():
    """Schemaを作成する.

    :return: 作成したSchemaの情報
    :rtype: Response
    """
    with MetaDataSession.begin():
        schema = Schema.create()
        schema.update_from_json(request.json)
        MetaDataSession.add(schema)

    return respond_success(schema=schema.to_json(with_modules=True))
Ejemplo n.º 9
0
    def test_module(self, _input, expected, mock_circlecore):
        module = Module.create()

        schema = Schema.create(display_name='Schema', properties='x:int,y:float')
        box = MessageBox(
            uuid=generate_uuid(model=MessageBox), schema_uuid=schema.uuid, module_uuid=module.uuid, display_name='Box'
        )

        _input['messageBoxes'] = [dict(schema=schema.uuid, displayName='Box2', memo='memo')]
        module.update_from_json(_input, with_boxes=True)

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        module = Module.query.get(module.uuid)
        assert isinstance(module, Module)
        assert module.display_name == expected['displayName']

        assert isinstance(module.tags, list)
        assert len(module.tags) == len(expected['tags'])
        for tag, exp_tag in zip(module.tags, expected['tags']):
            assert isinstance(tag, str)
            assert tag == exp_tag

        assert isinstance(module.attributes, ModuleAttributes)
        assert len(module.attributes) == len(expected['attributes'])
        for attr, exp_attr in zip(module.attributes, expected['attributes']):
            assert isinstance(attr, ModuleAttribute)
            assert attr.name == exp_attr[0]
            assert attr.value == exp_attr[1]

        assert module.memo == expected['memo']

        assert isinstance(hash(module), int)

        jsonobj = module.to_json(with_boxes=True, with_schema=True, with_cc_info=True)
        assert str(module.uuid) == jsonobj['uuid']
        assert str(module.cc_uuid) == jsonobj['ccUuid']
        assert module.display_name == jsonobj['displayName']
        for tag, json_tag in zip(module.tags, jsonobj['tags']):
            assert tag == json_tag
        for attr, json_attr in zip(module.attributes, jsonobj['attributes']):
            assert attr.name == json_attr['name']
            assert attr.value == json_attr['value']
        assert module.memo == jsonobj['memo']
        assert len(jsonobj['messageBoxes']) == 2
        assert jsonobj['ccInfo']
        assert jsonobj['isReplication'] is False
Ejemplo n.º 10
0
async def test_store_blob(mysql, mock_circlecore):
    envdir = mock_circlecore[1]

    with MetaDataSession.begin():
        ccinfo = CcInfo.query.filter_by(myself=True).one()

        module = Module.create()
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float,data:blob')
        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema=schema,
                         module=module,
                         display_name='Box')

        MetaDataSession.add(schema)
        MetaDataSession.add(module)
        MetaDataSession.add(box)

    database = Database(mysql.url, time_db_dir=envdir, log_dir=envdir)
    connection = database._engine.connect()

    with database._engine.begin() as connection:
        database.store_message(
            box,
            ModuleMessage(
                box.uuid,
                '1545895047.000',
                0,
                {
                    'x':
                    0,
                    'y':
                    3.14,
                    'data':
                    BlobMetadata(ccinfo.uuid, 'text/plain',
                                 'deadbeafdeadbeafdeadbeafdeadbeaf')
                },
            ),
            connection=connection)

    with database._engine.begin() as connection:
        table = database.find_table_for_message_box(box)
        rows = connection.execute(select([table.c.data])).fetchall()
        print(rows)
        assert len(rows) == 1
        expected = '{{"$data": "deadbeafdeadbeafdeadbeafdeadbeaf", "$source": "{source}", "$type": "text/plain"}}' \
            .format(
                source=str(ccinfo.uuid)
            )
        assert rows[0][0] == expected
Ejemplo n.º 11
0
async def test_datareceiver_store_blob(mock_circlecore, mysql, monkeypatch):
    metadata_db_engine, tmp_dir = mock_circlecore

    writer_mock = MagicMock()
    make_writer_mock = Mock(name='make_writer', return_value=writer_mock)

    async def dummy_store(*args, **kwargs):
        return DEFAULT

    writer_mock.store.side_effect = dummy_store

    monkeypatch.setattr(Database, 'make_writer', make_writer_mock)

    # make test schema/mbox
    with MetaDataSession.begin():
        schema = Schema.create(display_name='Schema', properties='x:int,y:float,data:blob')
        module = Module.create(display_name='Module')
        mbox = MessageBox(uuid=generate_uuid(model=MessageBox), schema_uuid=schema.uuid, module_uuid=module.uuid)

        MetaDataSession.add(schema)
        MetaDataSession.add(module)
        MetaDataSession.add(mbox)

    core_mock = MagicMock()
    worker = DataReceiverWorker(
        core_mock,
        'worker_key',
        db_url=mysql.url,
        time_db_dir=tmp_dir,
        log_dir=tmp_dir,
        cycle_time=10,
        cycle_count=10,
    )

    datahash = (
        '2b7e36b16f8a849ef312f9ef5ff9b3f4281a8681d0657150899f1113a0eecfdb'
        'b4491da763159055b55e122e85281415b11897d268e124f9ef2b40457a63a465'
    )
    blobobj = StoredBlob(None, 'text/plain', datahash)
    await worker.receive_new_message(mbox.uuid, {'x': 1, 'y': 2.0, 'data': blobobj})

    publish_mock = core_mock.hub.publish
    publish_mock.assert_called_once()
    message = publish_mock.call_args[0][1]
    assert message.payload['data'].content_type == 'text/plain'
    assert message.payload['data'].datahash == datahash
Ejemplo n.º 12
0
def dummy_mbox():
    print("            setup before function")

    with mock_circlecore_context():

        mbox_id = uuid.uuid4()
        with MetaDataSession.begin():
            schema = Schema.create(display_name='Schema',
                                   properties='x:int,y:float')
            module = Module.create(display_name='Module')
            mbox = MessageBox(uuid=mbox_id,
                              schema_uuid=schema.uuid,
                              module_uuid=module.uuid)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        yield (schema, module, mbox)
Ejemplo n.º 13
0
    def test_websocket_auth_failed(self):
        """Websocketにも認証がいる"""
        # make dummy environ
        with MetaDataSession.begin():
            schema = Schema.create(display_name='Schema', properties='x:int,y:float')
            module = Module.create(display_name='Module')
            mbox = MessageBox(
                uuid='4ffab839-cf56-478a-8614-6003a5980855', schema_uuid=schema.uuid, module_uuid=module.uuid
            )

            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        with self.assertRaises(httpclient.HTTPClientError):
            dummy_module = yield websocket_connect(self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)))
            dummy_module.write_message(json.dumps({'x': 1, 'y': 2}))
            yield sleep(1)
            self.datareceiver.receive_new_message.assert_not_called()
Ejemplo n.º 14
0
    def test_schema(self, _input, expected, mock_circlecore):
        schema = Schema.create()
        schema.update_from_json(_input)

        module = Module.create(display_name='Module')
        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         display_name='Box')

        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        schema = Schema.query.get(schema.uuid)
        assert isinstance(schema, Schema)
        assert schema.display_name == expected['displayName']
        assert schema.memo == expected['memo']

        assert isinstance(schema.properties, SchemaProperties)
        assert len(schema.properties) == len(expected['properties'])
        for prop, exp_prop in zip(schema.properties, expected['properties']):
            assert isinstance(prop, SchemaProperty)
            assert prop.name == exp_prop[0]
            assert prop.type == exp_prop[1]

        assert isinstance(hash(schema), int)

        jsonobj = schema.to_json(with_modules=True)
        assert str(schema.uuid) == jsonobj['uuid']
        assert str(schema.cc_uuid) == jsonobj['ccUuid']
        assert schema.display_name == jsonobj['displayName']
        for prop, json_prop in zip(schema.properties, jsonobj['properties']):
            assert prop.name == json_prop['name']
            assert prop.type == json_prop['type']
        assert schema.memo == jsonobj['memo']

        assert len(jsonobj['modules']) == 1
        assert module.display_name == jsonobj['modules'][0]['displayName']
Ejemplo n.º 15
0
    def test_update_from_json(self, _input, expected, mock_circlecore):
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')
        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema_uuid=schema.uuid,
                         module_uuid=module.uuid,
                         display_name='MessageBoxOldName')
        with MetaDataSession.begin():
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        box.update_from_json(_input)
        with MetaDataSession.begin():
            MetaDataSession.add(box)

        box = MessageBox.query.get(box.uuid)
        assert isinstance(box, MessageBox)
        assert box.display_name == expected['display_name']
        assert box.memo == expected['memo']
Ejemplo n.º 16
0
    def test_websocket_pass_to_nanomsg(self):
        """WebSocketで受け取ったModuleからのMessageに適切なtimestamp/countを付与してnanomsgに流せているかどうか."""

        # make dummy environ
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema', properties='x:int,y:float')
            module = Module.create(display_name='Module')
            mbox = MessageBox(
                uuid='4ffab839-cf56-478a-8614-6003a5980855', schema_uuid=schema.uuid, module_uuid=module.uuid
            )

            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        dummy_module = yield websocket_connect(
            httpclient.HTTPRequest(
                self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
                headers={
                    'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
                }
            )
        )
        dummy_module.write_message(json.dumps({'x': 1, 'y': 2}))

        # 素直にrecvするとIOLoopがブロックされてModuleHandlerが何も返せなくなるのでModuleHandlerをまず動かす
        yield sleep(1)
        self.datareceiver.receive_new_message.assert_called_once_with(
            '4ffab839-cf56-478a-8614-6003a5980855', {
                'x': 1,
                'y': 2
            }
        )
Ejemplo n.º 17
0
    def test_rest_with_data(self):
        """登録されているModuleからのPOSTは404"""
        # make dummy environ
        with MetaDataSession.begin():
            user = User.create(account='tester', password='******')
            user.renew_token()
            schema = Schema.create(display_name='Schema', properties='x:int,y:float,data:blob')
            module = Module.create(display_name='Module')
            mbox = MessageBox(
                uuid='4ffab839-cf56-478a-8614-6003a5980857', schema_uuid=schema.uuid, module_uuid=module.uuid
            )
            MetaDataSession.add(user)
            MetaDataSession.add(schema)
            MetaDataSession.add(module)
            MetaDataSession.add(mbox)

        async def _async_side_effect():
            print('_async_side_effect')
            return True

        # data encodingはOK
        response = self.fetch(
            self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
            method='POST',
            body=json.dumps({
                'x': 10.,
                'y': 20.5,
                'data': encode_to_data(*load_file('test.jpg'))
            }),
            headers={
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
            }
        )
        self.assertEqual(response.code, 200)
        self.datareceiver.receive_new_message.assert_called_once()
        args, kwargs = self.datareceiver.receive_new_message.call_args
        assert args[0] == str(mbox.uuid)
        assert args[1]['x'] == 10.
        assert args[1]['y'] == 20.5
        assert args[1]['data'].startswith('data:image/jpeg;')

        self.reset_mock()

        # そうじゃないのはNG
        response = self.fetch(
            self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
            method='POST',
            body=json.dumps({
                'x': 10.,
                'y': 20.5,
                'data': 'hogehoge'
            }),
            headers={
                'Content-Type': 'application/json',
                'Authorization': 'Bearer {token}'.format(token=user.encoded_token),
            }
        )
        self.assertEqual(response.code, 400)
        self.datareceiver.receive_new_message.assert_not_called()

        self.reset_mock()

        # multipartもOK
        body, headers = make_multipart_request(
            'application/json', json.dumps({
                'x': 10.,
                'y': 20.5,
                'data': 'file:///test.jpg'
            }), 'test.jpg'
        )
        headers['Authorization'] = 'Bearer {token}'.format(token=user.encoded_token)
        response = self.fetch(
            self.get_url('/modules/{}/{}'.format(module.uuid, mbox.uuid)),
            method='POST',
            headers=headers,
            body=body,
        )
        self.assertEqual(response.code, 200)
        args, kwargs = self.datareceiver.receive_new_message.call_args
        assert args[0] == str(mbox.uuid)
        assert args[1]['x'] == 10.
        assert args[1]['y'] == 20.5
        assert 'data' in args[1]
Ejemplo n.º 18
0
async def test():
    counterloop = asyncio.ensure_future(countup())

    setup_db()

    mbox_id = uuid.UUID('49EB92A3-AAE8-43A1-BC43-B7933DE96C6A')
    with MetaDataSession.begin():
        schema = Schema.create(display_name='Schema',
                               properties='x:int,y:float')
        module = Module.create(display_name='Module')
        mbox = MessageBox(uuid=mbox_id,
                          schema_uuid=schema.uuid,
                          module_uuid=module.uuid)
        MetaDataSession.merge(schema)
        MetaDataSession.merge(module)
        MetaDataSession.merge(mbox)

    database = Database('mysql+pymysql://root:hogehoge@localhost/crcr_test',
                        './tmp/',
                        './tmp/',
                        connect_args=dict(write_timeout=3, read_timeout=3))
    database.drop_message_box(mbox)

    queued_writer = QueuedDBWriter(database, './tmp/')

    class Delegate(QueuedDBWriterDelegate):
        async def on_reconnect(self) -> None:
            print('on_reconnect')
            writer.touch()

    queued_writer = QueuedDBWriter(database, './tmp/', delegate=Delegate())
    writer = JournalDBWriter(queued_writer, './tmp/')

    print('connect')
    # input('> ')
    database.connect()

    print('store')
    # input('> ')
    message = ModuleMessage(mbox.uuid, 123456.789, 0, {'x': 1, 'y': 2})
    assert (await writer.store(mbox, message)) is True

    print('store2 , please shutdown mysql')
    await async_input('> ')

    message = ModuleMessage(mbox.uuid, 123457.0, 1, {'x': 3, 'y': 4})
    assert (await writer.store(mbox, message)) is True

    assert (await writer.store(
        mbox, ModuleMessage(mbox.uuid, 123458.0, 2, {
            'x': 4,
            'y': 4
        }))) is True
    assert (await writer.store(
        mbox, ModuleMessage(mbox.uuid, 123459.0, 3, {
            'x': 5,
            'y': 4
        }))) is True
    assert (await writer.store(
        mbox, ModuleMessage(mbox.uuid, 123460.0, 4, {
            'x': 6,
            'y': 4
        }))) is True
    assert (await writer.store(
        mbox, ModuleMessage(mbox.uuid, 123461.0, 5, {
            'x': 7,
            'y': 4
        }))) is True

    print('store3 , please wakeup mysql')
    await async_input('> ')

    logger.info('DONE!')
    global done
    done = True
    await counterloop
Ejemplo n.º 19
0
async def test_replicate_blob(mysql, mock_circlecore):
    """BLOBをReplicateできるかテスト

    このテストは見ている範囲が広すぎるにしてはみたいところがみれてないのでは"""
    mock_cc = MagicMock()
    envdir = mock_circlecore[1]

    database = Database(mysql.url, time_db_dir=envdir, log_dir=envdir)

    with MetaDataSession.begin():
        master_uuid = generate_uuid(model=CcInfo)

        # ccinfo = CcInfo.query.filter_by(myself=True).one()
        master_cc_info = CcInfo(uuid=master_uuid,
                                display_name='test master',
                                myself=False,
                                work='')
        replication_master = ReplicationMaster(endpoint_url='',
                                               info=master_cc_info)
        module = Module(uuid=generate_uuid(model=Module),
                        cc_info=master_cc_info)
        schema = Schema.create(cc_uuid=master_cc_info.uuid,
                               display_name='Schema',
                               properties='x:int,y:float,data:blob')
        box = MessageBox(uuid=generate_uuid(model=MessageBox),
                         schema=schema,
                         module=module,
                         display_name='Box')

        MetaDataSession.add(master_cc_info)
        MetaDataSession.add(replication_master)
        MetaDataSession.add(module)
        MetaDataSession.add(schema)
        MetaDataSession.add(box)

    async def dummy_store(*args):
        return DEFAULT

    slave_dirver = SlaveDriverWorker(mock_cc, '', False)
    slave_dirver.initialize()
    assert len(slave_dirver.replicators) == 1
    assert replication_master.id in slave_dirver.replicators

    replicator = slave_dirver.replicators[replication_master.id]
    replicator.state = ReplicationState.SYNCING
    replicator.target_boxes = {box.uuid: box}
    replicator.ws = MagicMock()

    writer = QueuedDBWriter(database, envdir)
    replicator.writer = writer

    datahash = (
        'bf3408132f944568dd02827441f8c69b1f3e5a36bd7693a7aeeffd490037b56d'
        '9ad9406892ecd70cb9c0d31a746e7e790e731ae491dc0176a49369a2a4044581')
    replicator.ws.read_message = Mock(side_effect=make_dummy_read_message('''\
{{
    "command": "new_message",
    "message": {{
        "boxId": "{box_id}",
        "timestamp": "1546006083.213117",
        "counter": 0,
        "payload": {{
            "x": 32768,
            "y": 3.14,
            "data": {{"$data": "{datahash}", "$source": "{source}", "$type": "text/plain"}}
        }}
    }}
}}
'''.format(box_id=str(box.uuid), datahash=datahash,
           source=master_cc_info.uuid)))
    await replicator.wait_command((MasterCommand.NEW_MESSAGE, ))

    replicator.ws.read_message.assert_called_once()

    with database._engine.begin() as connection:
        table = database.find_table_for_message_box(box)
        rows = connection.execute(select([table.c.data])).fetchall()

        assert len(rows) == 1
        expected = '{{"$data": "{datahash}", "$source": "{source}", "$type": "text/plain"}}' \
            .format(
                datahash=datahash,
                source=str(master_cc_info.uuid)
            )
        assert rows[0][0] == expected