// Path: contrib/grpc-contrib/src/main/java/com/salesforce/grpc/contrib/Statuses.java
// public final class Statuses {
//     private Statuses() { }
// 
//     /**
//      * Evaluates a throwable to determine it if has a gRPC status. Particularly, is this throwable a
//      * {@code StatusException} or a {@code StatusRuntimeException}.
//      *
//      * @param t A throwable to evaluate
//      * @return {@code true} if {@code t} is a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static boolean hasStatus(Throwable t) {
//         return t instanceof StatusException || t instanceof StatusRuntimeException;
//     }
// 
//     /**
//      * Evaluates a throwable to determine if it has a gRPC status, and then if so, evaluates the throwable's
//      * status code.
//      *
//      * @param t A throwable to evaluate
//      * @param code A {@code Status.Code} to look for
//      * @return {@code true} if {@code t} is a {@code StatusException} or a {@code StatusRuntimeException} with
//      * {@code Status.Code} equal to {@code code}
//      */
//     public static boolean hasStatusCode(Throwable t, Status.Code code) {
//         if (!hasStatus(t)) {
//             return false;
//         } else {
//             return doWithStatus(t, (status, metadata) -> status.getCode() == code);
//         }
//     }
// 
//     /**
//      * Executes an action on a {@code StatusException} or a {@code StatusRuntimeException}, passing in the exception's
//      * metadata and trailers.
//      *
//      * @param t a {@code StatusException} or a {@code StatusRuntimeException}
//      * @param action the action to execute, given the exception's status and trailers
//      *
//      * @throws IllegalArgumentException if {@code t} is not a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static void doWithStatus(Throwable t, BiConsumer<Status, Metadata> action) {
//         doWithStatus(t, (status, metadata) -> {
//             action.accept(status, metadata);
//             return true;
//         });
//     }
// 
//     /**
//      * Executes a function on a {@code StatusException} or a {@code StatusRuntimeException}, passing in the exception's
//      * metadata and trailers.
//      *
//      * @param t a {@code StatusException} or a {@code StatusRuntimeException}
//      * @param function the function to execute, given the exception's status and trailers
//      * @param <T> the function's return type
//      *
//      * @throws IllegalArgumentException if {@code t} is not a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static <T> T doWithStatus(Throwable t, BiFunction<Status, Metadata, T> function) {
//         if (t instanceof StatusException) {
//             return function.apply(((StatusException) t).getStatus(), ((StatusException) t).getTrailers());
//         }
//         if (t instanceof StatusRuntimeException) {
//             return function.apply(((StatusRuntimeException) t).getStatus(), ((StatusRuntimeException) t).getTrailers());
//         }
// 
//         throw new IllegalArgumentException("Throwable " + t.getClass().getSimpleName() + " is neither a " +
//                 "StatusException nor a StatusRuntimeException");
//     }
// }


import com.salesforce.grpc.contrib.GreeterGrpc;
import com.salesforce.grpc.contrib.HelloRequest;
import com.salesforce.grpc.contrib.HelloResponse;
import com.salesforce.grpc.contrib.Statuses;
import io.grpc.*;
import io.grpc.stub.StreamObserver;
import io.grpc.testing.GrpcServerRule;
import org.assertj.core.api.Condition;
import org.junit.Rule;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc
                .newBlockingStub(serverRule.getChannel())
                .withInterceptors(new AmbientContextClientInterceptor("ctx-"));

        // Test
        AmbientContext.initialize(Context.current()).run(() -> {
            Metadata.Key<String> k = Metadata.Key.of("ctx-test", Metadata.ASCII_STRING_MARSHALLER);
            AmbientContext.current().put(k, "v");

            stub.sayHello(HelloRequest.newBuilder().setName("World").build());
        });
    }

    @Test
    public void serverEnforcerFailsMissing() {
        // Plumbing
        serverRule.getServiceRegistry().addService(ServerInterceptors.interceptForward(svc,
                new AmbientContextServerInterceptor("ctx-"),
                new AmbientContextEnforcerServerInterceptor("ctx-test")
        ));
        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc
                .newBlockingStub(serverRule.getChannel())
                .withInterceptors(new AmbientContextClientInterceptor("ctx-"));

        // Test
        assertThatThrownBy(() -> stub.sayHello(HelloRequest.newBuilder().setName("World").build()))
                .isInstanceOfAny(StatusRuntimeException.class)
                .has(new Condition<Throwable>() {
                    @Override
                    public boolean matches(Throwable throwable) {
// Path: contrib/grpc-contrib/src/main/java/com/salesforce/grpc/contrib/Statuses.java
// public final class Statuses {
//     private Statuses() { }
// 
//     /**
//      * Evaluates a throwable to determine it if has a gRPC status. Particularly, is this throwable a
//      * {@code StatusException} or a {@code StatusRuntimeException}.
//      *
//      * @param t A throwable to evaluate
//      * @return {@code true} if {@code t} is a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static boolean hasStatus(Throwable t) {
//         return t instanceof StatusException || t instanceof StatusRuntimeException;
//     }
// 
//     /**
//      * Evaluates a throwable to determine if it has a gRPC status, and then if so, evaluates the throwable's
//      * status code.
//      *
//      * @param t A throwable to evaluate
//      * @param code A {@code Status.Code} to look for
//      * @return {@code true} if {@code t} is a {@code StatusException} or a {@code StatusRuntimeException} with
//      * {@code Status.Code} equal to {@code code}
//      */
//     public static boolean hasStatusCode(Throwable t, Status.Code code) {
//         if (!hasStatus(t)) {
//             return false;
//         } else {
//             return doWithStatus(t, (status, metadata) -> status.getCode() == code);
//         }
//     }
// 
//     /**
//      * Executes an action on a {@code StatusException} or a {@code StatusRuntimeException}, passing in the exception's
//      * metadata and trailers.
//      *
//      * @param t a {@code StatusException} or a {@code StatusRuntimeException}
//      * @param action the action to execute, given the exception's status and trailers
//      *
//      * @throws IllegalArgumentException if {@code t} is not a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static void doWithStatus(Throwable t, BiConsumer<Status, Metadata> action) {
//         doWithStatus(t, (status, metadata) -> {
//             action.accept(status, metadata);
//             return true;
//         });
//     }
// 
//     /**
//      * Executes a function on a {@code StatusException} or a {@code StatusRuntimeException}, passing in the exception's
//      * metadata and trailers.
//      *
//      * @param t a {@code StatusException} or a {@code StatusRuntimeException}
//      * @param function the function to execute, given the exception's status and trailers
//      * @param <T> the function's return type
//      *
//      * @throws IllegalArgumentException if {@code t} is not a {@code StatusException} or a {@code StatusRuntimeException}
//      */
//     public static <T> T doWithStatus(Throwable t, BiFunction<Status, Metadata, T> function) {
//         if (t instanceof StatusException) {
//             return function.apply(((StatusException) t).getStatus(), ((StatusException) t).getTrailers());
//         }
//         if (t instanceof StatusRuntimeException) {
//             return function.apply(((StatusRuntimeException) t).getStatus(), ((StatusRuntimeException) t).getTrailers());
//         }
// 
//         throw new IllegalArgumentException("Throwable " + t.getClass().getSimpleName() + " is neither a " +
//                 "StatusException nor a StatusRuntimeException");
//     }
// }


// Path: contrib/grpc-contrib/src/test/java/com/salesforce/grpc/contrib/context/AmbientContextEnforcerTest.java
import com.salesforce.grpc.contrib.GreeterGrpc;
import com.salesforce.grpc.contrib.HelloRequest;
import com.salesforce.grpc.contrib.HelloResponse;
import com.salesforce.grpc.contrib.Statuses;
import io.grpc.*;
import io.grpc.stub.StreamObserver;
import io.grpc.testing.GrpcServerRule;
import org.assertj.core.api.Condition;
import org.junit.Rule;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc
                .newBlockingStub(serverRule.getChannel())
                .withInterceptors(new AmbientContextClientInterceptor("ctx-"));

        // Test
        AmbientContext.initialize(Context.current()).run(() -> {
            Metadata.Key<String> k = Metadata.Key.of("ctx-test", Metadata.ASCII_STRING_MARSHALLER);
            AmbientContext.current().put(k, "v");

            stub.sayHello(HelloRequest.newBuilder().setName("World").build());
        });
    }

    @Test
    public void serverEnforcerFailsMissing() {
        // Plumbing
        serverRule.getServiceRegistry().addService(ServerInterceptors.interceptForward(svc,
                new AmbientContextServerInterceptor("ctx-"),
                new AmbientContextEnforcerServerInterceptor("ctx-test")
        ));
        GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc
                .newBlockingStub(serverRule.getChannel())
                .withInterceptors(new AmbientContextClientInterceptor("ctx-"));

        // Test
        assertThatThrownBy(() -> stub.sayHello(HelloRequest.newBuilder().setName("World").build()))
                .isInstanceOfAny(StatusRuntimeException.class)
                .has(new Condition<Throwable>() {
                    @Override
                    public boolean matches(Throwable throwable) {
                        return Statuses.hasStatusCode(throwable, Status.Code.FAILED_PRECONDITION);