Example #1
0
def test_hack_and_slash_execute(fx_user, fx_novice_status):
    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])
    avatar = fx_user.avatar()
    avatar.hp = 0
    move = fx_user.move(HackAndSlash())
    Block.create(fx_user, [move])
    with raises(InvalidMoveError):
        move.execute(avatar)
Example #2
0
def test_execute_raise_invalid_move_error(
        fx_user: User, fx_novice_status: typing.Mapping[str, str]):
    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])
    for move_type in Move.__subclasses__():
        move = fx_user.move(move_type())
        assert not move.block
        assert not move.block_id
        with raises(InvalidMoveError):
            move.execute()
Example #3
0
def test_sync_node_unavailable_on_get_last_block(
        fx_user: User, fx_session: scoped_session, fx_other_session: Session,
        fx_server: WSGIServer, fx_novice_status: typing.Mapping[str, str],
        code: int):
    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])
    with Mocker() as m:
        m.get(url=f'{fx_server.url}/blocks/last', status_code=code)
        Block.sync(Node(url=fx_server.url), fx_other_session)
        assert fx_other_session.query(Block).count() == 0
Example #4
0
def test_ensure_block(fx_user: User):
    class ValidMove(Move):
        __mapper_args__ = {
            'polymorphic_identity': 'valid',
        }

    move = fx_user.move(ValidMove())
    Block.create(fx_user, [move])
    assert move.block
    assert move.block_id
    with raises(NotImplementedError):
        move.execute()
Example #5
0
def test_sync(fx_user, fx_session, fx_other_user, fx_other_session, fx_server,
              fx_novice_status):
    assert fx_other_session.query(Block).count() == 0
    assert fx_session.query(Block).count() == 0

    Block.sync(Node(url=fx_server.url), fx_other_session)
    assert fx_other_session.query(Block).count() == 0
    assert fx_session.query(Block).count() == 0

    Block.create(fx_other_user, [])
    Block.sync(Node(url=fx_server.url), fx_other_session)
    assert fx_other_session.query(Block).count() == 1
    assert fx_session.query(Block).count() == 0

    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])
    Block.create(fx_user, [])
    Block.create(fx_user, [])

    assert fx_other_session.query(Block).count() == 1
    assert fx_other_session.query(Move).count() == 0
    assert fx_session.query(Block).count() == 3
    assert fx_session.query(Move).count() == 1

    Block.sync(Node(url=fx_server.url), fx_other_session)
    assert fx_other_session.query(Block).count() == 3
    assert fx_other_session.query(Move).count() == 1
    assert fx_session.query(Block).count() == 3
    assert fx_session.query(Move).count() == 1
Example #6
0
def test_move(fx_test_client, fx_session, fx_user, fx_private_key):
    rv = fx_test_client.post('/login',
                             data={
                                 'private_key': fx_private_key.to_hex(),
                                 'name': 'test_user',
                             },
                             follow_redirects=True)
    rv = fx_test_client.post('/new')
    Block.create(fx_user,
                 fx_session.query(Move).filter_by(block_id=None).all())

    rv = fx_test_client.post('/session_moves',
                             data={
                                 'name': 'first_class',
                                 'class_': 'swordman',
                             },
                             follow_redirects=True)
    Block.create(fx_user,
                 fx_session.query(Move).filter_by(block_id=None).all())

    avatar = fx_user.avatar()
    assert avatar.class_ == 'swordman'

    rv = fx_test_client.get('/')
    assert rv.status == '200 OK'

    rv = fx_test_client.post('/session_moves',
                             data={'name': 'hack_and_slash'},
                             follow_redirects=True)
    assert rv.status == '200 OK'
    Block.create(fx_user,
                 fx_session.query(Move).filter_by(block_id=None).all())

    rv = fx_test_client.post('/session_moves',
                             data={'name': 'sleep'},
                             follow_redirects=True)
    assert rv.status == '200 OK'
    Block.create(fx_user,
                 fx_session.query(Move).filter_by(block_id=None).all())

    rv = fx_test_client.post('/session_moves',
                             data={
                                 'name': 'say',
                                 'content': 'hi!',
                             },
                             follow_redirects=True)
    assert rv.status == '200 OK'
    Block.create(fx_user,
                 fx_session.query(Move).filter_by(block_id=None).all())
Example #7
0
def test_sync_node_unaviable_on_branch_point(
        fx_user: User, fx_session: scoped_session, fx_server: WSGIServer,
        fx_other_session: Session, fx_novice_status: typing.Mapping[str, str],
        code: int):
    move = fx_user.create_novice(fx_novice_status)
    block = Block.create(fx_user, [move])
    Block.sync(Node(url=fx_server.url), fx_other_session)
    assert fx_other_session.query(Block).count() == 1
    serialized = block.serialize(use_bencode=False,
                                 include_suffix=True,
                                 include_moves=True,
                                 include_hash=True)
    serialized['id'] = block.id + 1
    with Mocker() as m:
        m.register_uri(
            'GET',
            f'{fx_server.url}/blocks/last',
            json={'block': serialized},
            status_code=200,
        )
        m.register_uri(
            'GET',
            f'{fx_server.url}/blocks/1',
            status_code=code,
        )
        assert not Block.sync(Node(url=fx_server.url), fx_other_session)
Example #8
0
def test_broadcast_block(
        fx_server: WSGIServer,
        fx_session: scoped_session,
        fx_other_session: Session,
        fx_other_server: WSGIServer,
        fx_user: User
):
    now = datetime.datetime.utcnow()
    node = Node(url=fx_server.url,
                last_connected_at=now)
    node2 = Node(url=fx_other_server.url,
                 last_connected_at=datetime.datetime.utcnow())
    block = Block.create(fx_user, [])
    fx_session.add_all([node, node2, block])
    fx_session.flush()
    assert fx_session.query(Block).get(block.id)
    assert not fx_other_session.query(Block).get(block.id)
    multicast(
        serialized=block.serialize(
            use_bencode=False,
            include_suffix=True,
            include_moves=True,
            include_hash=True
        ),
        broadcast=broadcast_block,
    )
    assert node.last_connected_at > now
    assert fx_session.query(Block).count() == 1
    assert fx_other_session.query(Block).get(block.id)
Example #9
0
def test_block_validation(fx_user, fx_novice_status):
    move = fx_user.create_novice(fx_novice_status)
    block = Block.create(fx_user, [move])
    assert block.valid
    move.id = ('00000000000000000000000000000000'
               '00000000000000000000000000000000')
    assert not block.valid
Example #10
0
def test_broadcast_block_retry(fx_session: scoped_session, fx_user: User,
                               limit: int, blocks: int, expected: int):
    for i in range(blocks):
        block = Block.create(fx_user, [])
    url = 'http://test.neko'
    now = datetime.datetime.utcnow()
    node = Node(url=url, last_connected_at=now)
    fx_session.add(node)
    fx_session.flush()
    patch = unittest.mock.patch('nekoyume.broadcast.BROADCAST_LIMIT', limit)
    with mock() as m, patch:
        m.register_uri('POST', 'http://test.neko/blocks', [{
            'json': {
                'result': 'failed',
                'block_id': 0,
                'mesage': "new block isn't our next block."
            },
            'status_code': 403
        }, {
            'json': {
                'result': 'success',
            },
            'status_code': 200
        }])
        broadcast_block(
            block.serialize(use_bencode=False,
                            include_suffix=True,
                            include_moves=True,
                            include_hash=True))
        assert m.call_count == expected
        assert node.last_connected_at > now
Example #11
0
def test_get_blocks(fx_test_client, fx_user):
    move = fx_user.sleep()

    rv = fx_test_client.get(f'/moves/{move.id}')
    assert rv.status == '200 OK'
    assert move.id.encode() in rv.data

    block = Block.create(fx_user, [move])

    rv = fx_test_client.get(f'/blocks')
    assert rv.status == '200 OK'
    assert block.hash.encode() in rv.data
    assert move.id.encode() in rv.data

    rv = fx_test_client.get(f'/blocks/{block.id}')
    assert rv.status == '200 OK'
    assert block.hash.encode() in rv.data
    assert move.id.encode() in rv.data

    rv = fx_test_client.get(f'/blocks/{block.hash}')
    assert rv.status == '200 OK'
    assert block.hash.encode() in rv.data

    rv = fx_test_client.get(f'/blocks/last')
    assert rv.status == '200 OK'
    assert block.hash.encode() in rv.data
Example #12
0
def test_post_block_return_block_id(fx_test_client: FlaskClient, fx_user: User,
                                    fx_session: scoped_session):
    block = Block.create(fx_user, [])
    fx_session.add(block)
    fx_session.commit()
    block2 = Block.create(fx_user, [])
    des = block2.serialize(use_bencode=False,
                           include_suffix=True,
                           include_moves=True,
                           include_hash=True)
    des['id'] = 3
    resp = fx_test_client.post('/blocks',
                               data=json.dumps(des),
                               content_type='application/json')
    assert resp.status_code == 403
    data = json.loads(resp.get_data())
    assert data['result'] == 'failed'
    assert data['message'] == "new block isn't our next block."
    assert data['block_id'] == 2
Example #13
0
def test_prevent_hack_and_slash_when_dead(
    fx_test_client: FlaskClient,
    fx_session: Session,
    fx_user: User,
    fx_private_key: PrivateKey,
    fx_novice_status: typing.Dict[str, str],
):
    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])

    assert fx_user.avatar().dead is False
    while fx_user.avatar().hp > 0:
        move = fx_user.hack_and_slash()
        Block.create(fx_user, [move])
    assert fx_user.avatar().dead is True

    response = fx_test_client.post('/session_moves',
                                   data={'name': 'hack_and_slash'})
    assert response.status_code == 302
Example #14
0
def test_broadcast_block_same_node(fx_session: scoped_session, fx_user: User):
    block = Block.create(fx_user, [])
    url = 'http://test.neko'
    now = datetime.datetime.utcnow()
    node = Node(url=url, last_connected_at=now)
    fx_session.add(node)
    fx_session.flush()
    broadcast_block(block.serialize(use_bencode=False,
                                    include_suffix=True,
                                    include_moves=True,
                                    include_hash=True),
                    sent_node=node)
    assert node.last_connected_at == now
Example #15
0
def test_post_move_broadcasting(
    fx_test_client: FlaskClient,
    fx_user: User,
    fx_private_key: PrivateKey,
    fx_session: scoped_session,
):
    with unittest.mock.patch('nekoyume.game.multicast') as m:
        fx_test_client.post('/login',
                            data={
                                'private_key': fx_private_key.to_hex(),
                                'name': 'test_user',
                            },
                            follow_redirects=True)
        fx_test_client.post('/new')
        Block.create(fx_user,
                     fx_session.query(Move).filter_by(block_id=None).all())
        assert not get_unconfirmed_move(fx_user.address)
        res = fx_test_client.post('/session_moves',
                                  data={'name': 'hack_and_slash'})
        assert res.status_code == 302
        move = fx_session.query(Move).filter(
            Move.name == 'hack_and_slash', ).first()
        assert move
        serialized = move.serialize(
            use_bencode=False,
            include_signature=True,
            include_id=True,
        )
        assert m.called
        args = m.call_args[1]
        assert serialized == args['serialized']
        my_node = args['my_node']
        assert isinstance(my_node, Node)
        assert my_node.url == 'http://localhost'
        broadcast = args['broadcast']
        assert isinstance(broadcast, typing.Callable)
        assert broadcast.__name__ == 'broadcast_move'
Example #16
0
def test_avatar_basic_moves(fx_user, fx_novice_status):
    moves = [
        CreateNovice(details=fx_novice_status),
        HackAndSlash(),
        Sleep(),
        Say(details={'content': 'hi'}),
        LevelUp(details={'new_status': 'strength'}),
    ]
    for move in moves:
        move = fx_user.move(move)
        block = Block.create(fx_user, [move])
        assert move.valid
        assert move.confirmed
        assert block.valid
        assert fx_user.avatar(block.id)
Example #17
0
def test_broadcast_block_raise_exception(fx_session: scoped_session,
                                         fx_user: User,
                                         error: typing.Union[ConnectionError,
                                                             Timeout]):
    block = Block.create(fx_user, [])
    url = 'http://test.neko'
    now = datetime.datetime.utcnow()
    node = Node(url=url, last_connected_at=now)
    fx_session.add(node)
    fx_session.flush()
    with Mocker() as m:
        m.post('http://test.neko/blocks', exc=error)
        broadcast_block(
            block.serialize(use_bencode=False,
                            include_suffix=True,
                            include_moves=True,
                            include_hash=True))
        assert node.last_connected_at == now
Example #18
0
def test_move_confirmed_and_validation(fx_user, fx_novice_status):
    move = Move()
    assert not move.confirmed
    assert not move.valid

    move = fx_user.create_novice(fx_novice_status)

    assert not move.confirmed
    assert move.valid

    block = Block.create(fx_user, [move])

    assert move.block_id
    assert move.confirmed
    assert move.valid

    move.tax = 1
    assert not move.valid
    assert not block.valid
Example #19
0
def test_broadcast_block_my_node(fx_session: scoped_session, fx_user: User):
    block = Block.create(fx_user, [])
    url = 'http://test.neko'
    now = datetime.datetime.utcnow()
    node = Node(url=url, last_connected_at=now)
    fx_session.add(node)
    fx_session.flush()
    with Mocker() as m:
        m.post('http://test.neko/blocks', text='success')
        expected = serialized = block.serialize(use_bencode=False,
                                                include_suffix=True,
                                                include_moves=True,
                                                include_hash=True)
        broadcast_block(serialized, my_node=node)
        expected['sent_node'] = url
        assert node.last_connected_at > now
        assert node.last_connected_at > now
        # check request.json value
        assert m.request_history[0].json() == expected
Example #20
0
def test_block_broadcast(fx_session: scoped_session, fx_user: User):
    block = Block.create(fx_user, [])
    fx_session.add(block)
    fx_session.commit()
    with unittest.mock.patch('nekoyume.tasks.broadcast_block') as m:
        block_broadcast(block.id,
                        'http://localhost:5000',
                        'http://localhost:5001',
                        session=fx_session)
        serialized = block.serialize(use_bencode=False,
                                     include_suffix=True,
                                     include_moves=True,
                                     include_hash=True)
        assert m.called
        args = m.call_args[1]
        assert serialized == args['serialized']
        assert isinstance(args['sent_node'], Node)
        assert args['sent_node'].url == 'http://localhost:5000'
        assert isinstance(args['my_node'], Node)
        assert args['my_node'].url == 'http://localhost:5001'
Example #21
0
def test_level_up(fx_user, fx_novice_status):
    move = fx_user.create_novice(fx_novice_status)
    Block.create(fx_user, [move])

    while True:
        if fx_user.avatar().exp >= 8:
            break
        move = fx_user.hack_and_slash()
        Block.create(fx_user, [move])

        if fx_user.avatar().hp <= 0:
            move = fx_user.sleep()
            Block.create(fx_user, [move])

    assert fx_user.avatar().level >= 2
Example #22
0
def test_find_branch_point(fx_session: scoped_session, fx_server: WSGIServer,
                           fx_user: User, value: int, high: int,
                           expected: int):
    node = Node(url=fx_server.url)
    Block.create(fx_user, [])
    assert find_branch_point(node, fx_session, value, high) == expected
Example #23
0
def test_flush_session_while_syncing(fx_user, fx_session, fx_other_session,
                                     fx_novice_status):
    # 1. block validation failure scenario
    # syncing without flushing can cause block validation failure
    move = fx_user.create_novice(fx_novice_status)
    invalid_block = Block.create(fx_user, [move])
    fx_session.delete(invalid_block)

    # syncing valid blocks from another node
    new_blocks = [
        {
            "created_at": "2018-04-13 11:36:17.920869",
            "creator": "ET8ngv45qwhkDiJS1ZrUxndcGTzHxjPZDs",
            "difficulty": 0,
            "hash":
            "da0182c494660af0d9dd288839ceb86498708f38c800363cd46ed1730013a4d8",  # noqa
            "id": 1,
            "version": 2,
            "moves": [],
            "prev_hash": None,
            "root_hash":
            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",  # noqa
            "suffix": "00"
        },
        {
            "created_at": "2018-04-13 11:36:17.935392",
            "creator": "ET8ngv45qwhkDiJS1ZrUxndcGTzHxjPZDs",
            "difficulty": 1,
            "hash":
            "014c44b9382a45c2a70d817c090e6b78af22b8f34b57fd7edb474344f25c439c",  # noqa
            "id": 2,
            "version": 2,
            "moves": [],
            "prev_hash":
            "da0182c494660af0d9dd288839ceb86498708f38c800363cd46ed1730013a4d8",  # noqa
            "root_hash":
            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",  # noqa
            "suffix": "0b"
        }
    ]

    def add_block(new_block):
        block = Block.deserialize(new_block)
        fx_session.add(block)
        return block

    valid_block1 = add_block(new_blocks[0])
    valid_block2 = add_block(new_blocks[1])

    assert invalid_block.hash == \
        fx_session.query(Block).get(valid_block2.id - 1).hash
    assert valid_block2.valid is False

    fx_session.query(Block).delete()

    # 2. valid scenario
    # flush session after deleting the invalid block
    move = fx_user.create_novice(fx_novice_status)
    invalid_block = Block.create(fx_user, [move])
    fx_session.delete(invalid_block)
    fx_session.flush()

    valid_block1 = add_block(new_blocks[0])
    valid_block2 = add_block(new_blocks[1])

    assert valid_block1.hash == \
        fx_session.query(Block).get(valid_block2.id - 1).hash
    assert valid_block2.valid