• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google LLC
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google LLC nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 package com.google.api.gax.grpc;
31 
32 import static com.google.api.gax.grpc.GrpcApiExceptionFactory.ERROR_DETAIL_KEY;
33 
34 import com.google.api.gax.rpc.ApiException;
35 import com.google.api.gax.rpc.ErrorDetails;
36 import com.google.common.collect.ImmutableList;
37 import com.google.common.truth.Truth;
38 import com.google.protobuf.Any;
39 import com.google.protobuf.Duration;
40 import com.google.rpc.ErrorInfo;
41 import com.google.rpc.RetryInfo;
42 import com.google.rpc.Status;
43 import io.grpc.Metadata;
44 import io.grpc.StatusException;
45 import io.grpc.StatusRuntimeException;
46 import java.util.Collections;
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.junit.runners.JUnit4;
51 
52 @RunWith(JUnit4.class)
53 public class GrpcApiExceptionFactoryTest {
54 
55   private static final ErrorInfo ERROR_INFO =
56       ErrorInfo.newBuilder()
57           .setDomain("googleapis.com")
58           .setReason("SERVICE_DISABLED")
59           .putAllMetadata(Collections.emptyMap())
60           .build();
61 
62   private static final RetryInfo RETRY_INFO =
63       RetryInfo.newBuilder().setRetryDelay(Duration.newBuilder().setSeconds(213).build()).build();
64 
65   private static final ImmutableList<Any> RAW_ERROR_MESSAGES =
66       ImmutableList.of(Any.pack(ERROR_INFO), Any.pack(RETRY_INFO));
67 
68   private static final ErrorDetails ERROR_DETAILS =
69       ErrorDetails.builder().setRawErrorMessages(RAW_ERROR_MESSAGES).build();
70 
71   private static final io.grpc.Status GRPC_STATUS = io.grpc.Status.CANCELLED;
72 
73   private GrpcApiExceptionFactory factory;
74 
75   @Before
setUp()76   public void setUp() throws Exception {
77     factory = new GrpcApiExceptionFactory(Collections.emptySet());
78   }
79 
80   @Test
create_shouldCreateApiExceptionWithErrorDetailsForStatusException()81   public void create_shouldCreateApiExceptionWithErrorDetailsForStatusException() {
82     Metadata trailers = new Metadata();
83     Status status = Status.newBuilder().addAllDetails(RAW_ERROR_MESSAGES).build();
84     trailers.put(
85         Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), status.toByteArray());
86     StatusException statusException = new StatusException(GRPC_STATUS, trailers);
87 
88     ApiException actual = factory.create(statusException);
89 
90     Truth.assertThat(actual.getErrorDetails()).isEqualTo(ERROR_DETAILS);
91   }
92 
93   @Test
create_shouldCreateApiExceptionWithErrorDetailsForStatusRuntimeException()94   public void create_shouldCreateApiExceptionWithErrorDetailsForStatusRuntimeException() {
95     Metadata trailers = new Metadata();
96     Status status = Status.newBuilder().addAllDetails(RAW_ERROR_MESSAGES).build();
97     trailers.put(
98         Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), status.toByteArray());
99     StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, trailers);
100 
101     ApiException actual = factory.create(statusException);
102 
103     Truth.assertThat(actual.getErrorDetails()).isEqualTo(ERROR_DETAILS);
104   }
105 
106   @Test
create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataIsNull()107   public void create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataIsNull() {
108     StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, null);
109 
110     ApiException actual = factory.create(statusException);
111 
112     Truth.assertThat(actual.getErrorDetails()).isNull();
113   }
114 
115   @Test
create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataDoesNotHaveErrorDetails()116   public void create_shouldCreateApiExceptionWithNoErrorDetailsIfMetadataDoesNotHaveErrorDetails() {
117     StatusRuntimeException statusException =
118         new StatusRuntimeException(GRPC_STATUS, new Metadata());
119 
120     ApiException actual = factory.create(statusException);
121 
122     Truth.assertThat(actual.getErrorDetails()).isNull();
123   }
124 
125   @Test
create_shouldCreateApiExceptionWithNoErrorDetailsIfStatusIsMalformed()126   public void create_shouldCreateApiExceptionWithNoErrorDetailsIfStatusIsMalformed() {
127     Metadata trailers = new Metadata();
128     Status status = Status.newBuilder().addDetails(Any.pack(ERROR_INFO)).build();
129     byte[] bytes = status.toByteArray();
130     // manually manipulate status bytes array
131     bytes[0] = 123;
132     trailers.put(Metadata.Key.of(ERROR_DETAIL_KEY, Metadata.BINARY_BYTE_MARSHALLER), bytes);
133     StatusRuntimeException statusException = new StatusRuntimeException(GRPC_STATUS, trailers);
134 
135     ApiException actual = factory.create(statusException);
136 
137     Truth.assertThat(actual.getErrorDetails()).isNull();
138   }
139 }
140