Exemple #1
0
def test_feedback(pathfinding_service_mock):
    token_network_address = TokenNetworkAddress(b"1" * 20)
    route = [Address(b"2" * 20), Address(b"3" * 20)]
    other_route = [Address(b"2" * 20), Address(b"4" * 20)]

    token = FeedbackToken(token_network_address=token_network_address)
    other_token = FeedbackToken(token_network_address=token_network_address)

    database = pathfinding_service_mock.database
    assert not db_has_feedback_for(database=database, token=token, route=route)
    assert not db_has_feedback_for(database=database, token=token, route=other_route)
    assert not db_has_feedback_for(database=database, token=other_token, route=route)

    database.prepare_feedback(token=token, route=route)
    assert not db_has_feedback_for(database=database, token=token, route=route)
    assert not db_has_feedback_for(database=database, token=other_token, route=route)
    assert not db_has_feedback_for(database=database, token=token, route=other_route)

    rowcount = database.update_feedback(token=token, route=route, successful=True)
    assert rowcount == 1
    assert db_has_feedback_for(database=database, token=token, route=route)
    assert not db_has_feedback_for(database=database, token=other_token, route=route)
    assert not db_has_feedback_for(database=database, token=token, route=other_route)

    rowcount = database.update_feedback(token=token, route=route, successful=True)
    assert rowcount == 0
def test_stats_endpoint(
    api_sut_with_debug: ServiceApi, api_url: str, token_network_model: TokenNetwork
):
    database = api_sut_with_debug.pathfinding_service.database
    default_path = [Address(b"1" * 20), Address(b"2" * 20), Address(b"3" * 20)]
    feedback_token = FeedbackToken(token_network_model.address)

    def check_response(num_all: int, num_only_feedback: int, num_only_success: int) -> None:
        url = api_url + f"/_debug/stats"
        response = requests.get(url)

        assert response.status_code == 200

        data = response.json()
        assert data["total_calculated_routes"] == num_all
        assert data["total_feedback_received"] == num_only_feedback
        assert data["total_successful_routes"] == num_only_success

    database.prepare_feedback(feedback_token, default_path)
    check_response(1, 0, 0)

    database.update_feedback(feedback_token, default_path, False)
    check_response(1, 1, 0)

    default_path2 = default_path[1:]
    feedback_token2 = FeedbackToken(token_network_model.address)

    database.prepare_feedback(feedback_token2, default_path2)
    check_response(2, 1, 0)

    database.update_feedback(feedback_token2, default_path2, True)
    check_response(2, 2, 1)
Exemple #3
0
def test_feedback_stats(pathfinding_service_mock):
    token_network_address = TokenNetworkAddress(b"1" * 20)
    default_path = [b"1" * 20, b"2" * 20, b"3" * 20]
    feedback_token = FeedbackToken(token_network_address)
    database = pathfinding_service_mock.database

    database.prepare_feedback(feedback_token, default_path)
    assert database.get_num_routes_feedback() == 1
    assert database.get_num_routes_feedback(only_with_feedback=True) == 0
    assert database.get_num_routes_feedback(only_successful=True) == 0

    database.update_feedback(feedback_token, default_path, False)
    assert database.get_num_routes_feedback() == 1
    assert database.get_num_routes_feedback(only_with_feedback=True) == 1
    assert database.get_num_routes_feedback(only_successful=True) == 0

    default_path2 = default_path[1:]
    feedback_token2 = FeedbackToken(token_network_address)

    database.prepare_feedback(feedback_token2, default_path2)
    assert database.get_num_routes_feedback() == 2
    assert database.get_num_routes_feedback(only_with_feedback=True) == 1
    assert database.get_num_routes_feedback(only_successful=True) == 0

    database.update_feedback(feedback_token2, default_path2, True)
    assert database.get_num_routes_feedback() == 2
    assert database.get_num_routes_feedback(only_with_feedback=True) == 2
    assert database.get_num_routes_feedback(only_successful=True) == 1
def test_feedback(api_sut: PFSApi, api_url: str,
                  token_network_model: TokenNetwork):
    database = api_sut.pathfinding_service.database
    default_path_hex = ["0x" + "1" * 40, "0x" + "2" * 40, "0x" + "3" * 40]
    default_path = [to_canonical_address(e) for e in default_path_hex]
    estimated_fee = FeeAmount(0)

    def make_request(token_id: Optional[str] = None,
                     success: bool = True,
                     path: Optional[List[str]] = None):
        url = api_url + f"/v1/{to_checksum_address(token_network_model.address)}/feedback"

        token_id = token_id or uuid4().hex
        path = path or default_path_hex
        data = {"token": token_id, "success": success, "path": path}
        return requests.post(url, json=data)

    # Request with invalid UUID
    response = make_request(token_id="abc")
    assert response.status_code == 400
    assert response.json(
    )["error_code"] == exceptions.InvalidRequest.error_code

    # Request with invalid path
    response = make_request(path=["abc"])
    assert response.status_code == 400
    assert response.json(
    )["error_code"] == exceptions.InvalidRequest.error_code

    # Test valid token, which is not stored in PFS DB
    token = FeedbackToken(token_network_address=token_network_model.address)

    response = make_request(token_id=token.uuid.hex)
    assert response.status_code == 400
    assert not db_has_feedback_for(database, token, default_path)

    # Test expired token
    old_token = FeedbackToken(
        creation_time=datetime.utcnow() - timedelta(hours=1),
        token_network_address=token_network_model.address,
    )
    database.prepare_feedback(old_token, default_path, estimated_fee)

    response = make_request(token_id=old_token.uuid.hex)
    assert response.status_code == 400
    assert not db_has_feedback_for(database, token, default_path)

    # Test valid token
    token = FeedbackToken(token_network_address=token_network_model.address)
    database.prepare_feedback(token, default_path, estimated_fee)

    response = make_request(token_id=token.uuid.hex)
    assert response.status_code == 200
    assert db_has_feedback_for(database, token, default_path)
Exemple #5
0
def test_feedback_token_validity():
    token_network_address = TokenNetworkAddress(b"1" * 20)

    # Newly created token is valid
    valid_token = FeedbackToken(token_network_address=token_network_address)
    assert valid_token.is_valid()

    # Test expiry in is_valid
    invalid_token = FeedbackToken(
        creation_time=datetime.utcnow() - MAX_AGE_OF_FEEDBACK_REQUESTS - timedelta(seconds=1),
        token_network_address=token_network_address,
    )
    assert not invalid_token.is_valid()
Exemple #6
0
    def get_feedback_token(self, token_id: UUID,
                           token_network_address: TokenNetworkAddress,
                           route: List[Address]) -> Optional[FeedbackToken]:
        hexed_route = [to_checksum_address(e) for e in route]
        token = self.conn.execute(
            """SELECT * FROM feedback WHERE
                token_id = ? AND
                token_network_address = ? AND
                route = ?;
            """,
            [
                token_id.hex,
                to_checksum_address(token_network_address),
                json.dumps(hexed_route)
            ],
        ).fetchone()

        if token:
            return FeedbackToken(
                token_network_address=decode_hex(
                    token["token_network_address"]),
                id=UUID(token["token_id"]),
                creation_time=token["creation_time"],
            )

        return None
Exemple #7
0
    def get_feedback_token(self, token_id: UUID,
                           token_network_address: TokenNetworkAddress,
                           route: List[Address]) -> Optional[FeedbackToken]:
        hexed_route = [to_checksum_address(e) for e in route]
        with self._cursor() as cursor:
            token = cursor.execute(
                """SELECT * FROM feedback WHERE
                    token_id = ? AND
                    token_network_address = ? AND
                    route = ?;
                """,
                [
                    token_id.hex,
                    to_checksum_address(token_network_address),
                    json.dumps(hexed_route),
                ],
            ).fetchone()

        if token:
            return FeedbackToken(
                token_network_address=TokenNetworkAddress(
                    to_canonical_address(token["token_network_address"])),
                uuid=UUID(token["token_id"]),
                creation_time=token["creation_time"],
            )

        return None
Exemple #8
0
def create_and_store_feedback_tokens(
    pathfinding_service: PathfindingService,
    token_network_address: TokenNetworkAddress,
    routes: List[Dict],
) -> FeedbackToken:
    feedback_token = FeedbackToken(token_network_address=token_network_address)

    # TODO: use executemany here
    for route in routes:
        pathfinding_service.database.prepare_feedback(token=feedback_token,
                                                      route=route["path"])

    return feedback_token
def create_and_store_feedback_tokens(
    pathfinding_service: PathfindingService,
    token_network_address: TokenNetworkAddress,
    routes: List[Path],
) -> FeedbackToken:
    with opentracing.tracer.start_span("store_feedback_token"):
        feedback_token = FeedbackToken(token_network_address=token_network_address)

        # TODO: use executemany here
        for route in routes:
            pathfinding_service.database.prepare_feedback(
                token=feedback_token, route=route.nodes, estimated_fee=route.estimated_fee
            )

        return feedback_token
Exemple #10
0
def test_insert_feedback_token(pathfinding_service_mock):
    token_network_address = TokenNetworkAddress(b"1" * 20)
    route = [Address(b"2" * 20), Address(b"3" * 20)]
    estimated_fee = -123

    token = FeedbackToken(token_network_address=token_network_address)
    database = pathfinding_service_mock.database
    database.prepare_feedback(token=token,
                              route=route,
                              estimated_fee=estimated_fee)

    # Test round-trip
    stored = database.get_feedback_token(
        token_id=token.uuid,
        token_network_address=token_network_address,
        route=route)
    assert stored == token

    # Test different UUID
    stored = database.get_feedback_token(
        token_id=uuid4(),
        token_network_address=token_network_address,
        route=route)
    assert stored is None

    # Test different token network address
    token_network_address_wrong = TokenNetworkAddress(b"9" * 20)
    stored = database.get_feedback_token(
        token_id=uuid4(),
        token_network_address=token_network_address_wrong,
        route=route)
    assert stored is None

    # Test different route
    route_wrong = [Address(b"2" * 20), Address(b"3" * 20), Address(b"4" * 20)]
    stored = database.get_feedback_token(
        token_id=uuid4(),
        token_network_address=token_network_address,
        route=route_wrong)
    assert stored is None

    # Test empty route
    stored = database.get_feedback_token(
        token_id=uuid4(),
        token_network_address=token_network_address,
        route=[])
    assert stored is None