def test_all_exceptions(interceptors):
    """Every gRPC status code is represented, and they each are unique.

    Make sure we aren't missing any status codes, and that we didn't copy paste the
    same status code or details into two different classes.
    """
    all_status_codes = {
        sc
        for sc in grpc.StatusCode if sc != grpc.StatusCode.OK
    }
    seen_codes = set()
    seen_details = set()

    for sc in all_status_codes:
        ex = getattr(gx, _snake_to_camel(sc.name))
        assert ex
        special_cases = {"error": raises(ex())}
        with dummy_client(special_cases=special_cases,
                          interceptors=interceptors) as client:
            with pytest.raises(grpc.RpcError) as e:
                client.Execute(DummyRequest(input="error"))
            assert e.value.code() == sc
            assert e.value.details() == ex.details
            seen_codes.add(sc)
            seen_details.add(ex.details)

    assert seen_codes == all_status_codes
    assert len(seen_details) == len(all_status_codes)
def test_basic_retry():
    """Calling the continuation multiple times should work."""
    interceptor = RetryInterceptor(retries=1)
    special_cases = {"error_once": CrashingService(num_crashes=1)}
    with dummy_client(special_cases=special_cases,
                      client_interceptors=[interceptor]) as client:
        assert client.Execute(DummyRequest(input="error_once")).output == "OK"
Exemple #3
0
def test_client_server_streaming(interceptors):
    """Bidirectional streaming should work."""
    with dummy_client(special_cases={}, interceptors=interceptors) as client:
        inputs = ["foo", "bar"]
        input_iter = (DummyRequest(input=input) for input in inputs)
        response = client.ExecuteClientServerStream(input_iter)
        assert [r.output for r in response] == inputs
Exemple #4
0
def test_server_streaming(interceptors):
    """Server streaming should work."""
    with dummy_client(special_cases={}, interceptors=interceptors) as client:
        output = [
            r.output
            for r in client.ExecuteServerStream(DummyRequest(input="foo"))
        ]
        assert output == ["f", "o", "o"]
def test_aborting_interceptor():
    """context.abort called in an interceptor works."""
    interceptor = AbortingInterceptor("oh no")
    with dummy_client(special_cases={}, interceptors=[interceptor]) as client:
        with pytest.raises(grpc.RpcError) as e:
            client.Execute(DummyRequest(input="test"))
        assert e.value.code() == grpc.StatusCode.ABORTED
        assert e.value.details() == "oh no"
def test_failed_retry():
    """The interceptor can return failed futures."""
    interceptor = RetryInterceptor(retries=1)
    special_cases = {"error_twice": CrashingService(num_crashes=2)}
    with dummy_client(special_cases=special_cases,
                      client_interceptors=[interceptor]) as client:
        with pytest.raises(grpc.RpcError):
            client.Execute(DummyRequest(input="error_twice"))
def test_non_grpc_exception(interceptors):
    """Exceptions other than GrpcExceptions are ignored."""
    special_cases = {"error": raises(ValueError("oops"))}
    with dummy_client(special_cases=special_cases,
                      interceptors=interceptors) as client:
        with pytest.raises(grpc.RpcError) as e:
            client.Execute(DummyRequest(input="error"))
        assert e.value.code() == grpc.StatusCode.UNKNOWN
def test_interceptor_chain():
    """Interceptors are called in the right order."""
    trace = []
    interceptor1 = SideEffectInterceptor(lambda: trace.append(1))
    interceptor2 = SideEffectInterceptor(lambda: trace.append(2))
    with dummy_client(special_cases={},
                      interceptors=[interceptor1, interceptor2]) as client:
        assert client.Execute(DummyRequest(input="test")).output == "test"
        assert trace == [1, 2]
def test_custom_details(interceptors):
    """We can set custom details."""
    special_cases = {"error": raises(gx.NotFound(details="custom"))}
    with dummy_client(special_cases=special_cases,
                      interceptors=interceptors) as client:
        assert (client.Execute(DummyRequest(input="foo")).output == "foo"
                )  # Test a happy path too
        with pytest.raises(grpc.RpcError) as e:
            client.Execute(DummyRequest(input="error"))
        assert e.value.code() == grpc.StatusCode.NOT_FOUND
        assert e.value.details() == "custom"
def test_non_grpc_exception_with_override():
    """We can set a custom status code when non-GrpcExceptions are raised."""
    interceptors = [
        ExceptionToStatusInterceptor(
            status_on_unknown_exception=grpc.StatusCode.INTERNAL)
    ]
    special_cases = {"error": raises(ValueError("oops"))}
    with dummy_client(special_cases=special_cases,
                      interceptors=interceptors) as client:
        with pytest.raises(grpc.RpcError) as e:
            client.Execute(DummyRequest(input="error"))
        assert e.value.code() == grpc.StatusCode.INTERNAL
        assert re.fullmatch(r"ValueError\('oops',?\)", e.value.details())
Exemple #11
0
def test_client_streaming(interceptors):
    """Client streaming should work."""
    special_cases = {"error": lambda r, c: 1 / 0}
    with dummy_client(special_cases=special_cases,
                      interceptors=interceptors) as client:
        inputs = ["foo", "bar"]
        input_iter = (DummyRequest(input=input) for input in inputs)
        assert client.ExecuteClientStream(input_iter).output == "foobar"

        inputs = ["foo", "error"]
        input_iter = (DummyRequest(input=input) for input in inputs)
        with pytest.raises(grpc.RpcError):
            client.ExecuteClientStream(input_iter)
def metadata_client():
    """Client with metadata interceptor."""
    intr = MetadataInterceptor([("this_key", "this_value")])
    interceptors = [intr]

    special_cases = {
        "metadata":
        lambda _, c: ",".join(f"{key}:{value}"
                              for key, value in c.invocation_metadata())
    }
    with dummy_client(special_cases=special_cases,
                      client_interceptors=interceptors) as client:
        yield client
def test_chaining():
    """Chaining interceptors should work."""
    retry_interceptor = RetryInterceptor(retries=1)
    code_count_interceptor = CodeCountInterceptor()
    interceptors = [retry_interceptor, code_count_interceptor]
    special_cases = {"error_once": CrashingService(num_crashes=1)}
    with dummy_client(special_cases=special_cases,
                      client_interceptors=interceptors) as client:
        assert code_count_interceptor.counts == {}
        assert client.Execute(DummyRequest(input="error_once")).output == "OK"
        assert code_count_interceptor.counts == {
            grpc.StatusCode.OK: 1,
            grpc.StatusCode.UNKNOWN: 1,
        }
def test_code_counting():
    """Access to code on call details works correctly."""
    interceptor = CodeCountInterceptor()
    special_cases = {"error": raises(ValueError("oops"))}
    with dummy_client(special_cases=special_cases,
                      client_interceptors=[interceptor]) as client:
        assert interceptor.counts == {}
        client.Execute(DummyRequest(input="foo"))
        assert interceptor.counts == {grpc.StatusCode.OK: 1}
        with pytest.raises(grpc.RpcError):
            client.Execute(DummyRequest(input="error"))
        assert interceptor.counts == {
            grpc.StatusCode.OK: 1,
            grpc.StatusCode.UNKNOWN: 1
        }
def test_call_counts():
    """The counts should be correct."""
    intr = CountingInterceptor()
    interceptors = [intr]

    special_cases = {"error": lambda r, c: 1 / 0}
    with dummy_client(special_cases=special_cases,
                      interceptors=interceptors) as client:
        assert client.Execute(DummyRequest(input="foo")).output == "foo"
        assert len(intr.num_calls) == 1
        assert intr.num_calls["/DummyService/Execute"] == 1
        assert len(intr.num_errors) == 0

        with pytest.raises(grpc.RpcError):
            client.Execute(DummyRequest(input="error"))

        assert len(intr.num_calls) == 1
        assert intr.num_calls["/DummyService/Execute"] == 2
        assert len(intr.num_errors) == 1
        assert intr.num_errors["/DummyService/Execute"] == 1
def test_caching():
    """Caching calls (not calling the continuation) should work."""
    caching_interceptor = CachingInterceptor()
    # Use this to test how many times the continuation is called.
    code_count_interceptor = CodeCountInterceptor()
    interceptors = [caching_interceptor, code_count_interceptor]
    with dummy_client(special_cases={},
                      client_interceptors=interceptors) as client:
        assert code_count_interceptor.counts == {}
        assert client.Execute(DummyRequest(input="hello")).output == "hello"
        assert code_count_interceptor.counts == {grpc.StatusCode.OK: 1}
        assert client.Execute(DummyRequest(input="hello")).output == "hello"
        assert code_count_interceptor.counts == {grpc.StatusCode.OK: 1}
        assert client.Execute(
            DummyRequest(input="goodbye")).output == "goodbye"
        assert code_count_interceptor.counts == {grpc.StatusCode.OK: 2}
        # Try streaming requests
        inputs = ["foo", "bar"]
        input_iter = (DummyRequest(input=input) for input in inputs)
        assert client.ExecuteClientStream(input_iter).output == "foobar"
        assert code_count_interceptor.counts == {grpc.StatusCode.OK: 3}
        input_iter = (DummyRequest(input=input) for input in inputs)
        assert client.ExecuteClientStream(input_iter).output == "foobar"
        assert code_count_interceptor.counts == {grpc.StatusCode.OK: 3}
def test_modifying_interceptor():
    """Interceptors can modify requests."""
    interceptor = UppercasingInterceptor()
    with dummy_client(special_cases={}, interceptors=[interceptor]) as client:
        assert client.Execute(DummyRequest(input="test")).output == "TEST"
def test_no_exception(interceptors):
    """An RPC with no exceptions should work as if the interceptor wasn't there."""
    with dummy_client(special_cases={}, interceptors=interceptors) as client:
        assert client.Execute(DummyRequest(input="foo")).output == "foo"