blob: f369453bb828ecacb29abaada07c530070e98882 [file] [log] [blame]
/*
* Copyright 2014 The gRPC Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.grpc.internal;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import io.grpc.CallOptions;
import io.grpc.LoadBalancer.PickResult;
import io.grpc.Metadata;
import io.grpc.Status;
import io.grpc.internal.ClientStreamListener.RpcProgress;
import io.grpc.internal.GrpcUtil.Http2Error;
import io.grpc.testing.TestMethodDescriptors;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link GrpcUtil}. */
@RunWith(JUnit4.class)
public class GrpcUtilTest {
@Rule public final ExpectedException thrown = ExpectedException.none();
@Test
public void http2ErrorForCode() {
// Try edge cases manually, to make the test obviously correct for important cases.
assertNull(Http2Error.forCode(-1));
assertSame(Http2Error.NO_ERROR, Http2Error.forCode(0));
assertSame(Http2Error.HTTP_1_1_REQUIRED, Http2Error.forCode(0xD));
assertNull(Http2Error.forCode(0xD + 1));
}
@Test
public void http2ErrorRoundTrip() {
for (Http2Error error : Http2Error.values()) {
assertSame(error, Http2Error.forCode(error.code()));
}
}
@Test
public void http2ErrorStatus() {
// Nothing special about this particular error, except that it is slightly distinctive.
assertSame(Status.Code.CANCELLED, Http2Error.CANCEL.status().getCode());
}
@Test
public void http2ErrorStatusForCode() {
assertSame(Status.Code.INTERNAL, Http2Error.statusForCode(-1).getCode());
assertSame(Http2Error.NO_ERROR.status(), Http2Error.statusForCode(0));
assertSame(Http2Error.HTTP_1_1_REQUIRED.status(), Http2Error.statusForCode(0xD));
assertSame(Status.Code.INTERNAL, Http2Error.statusForCode(0xD + 1).getCode());
}
@Test
public void timeoutTest() {
GrpcUtil.TimeoutMarshaller marshaller =
new GrpcUtil.TimeoutMarshaller();
// nanos
assertEquals("0n", marshaller.toAsciiString(0L));
assertEquals(0L, (long) marshaller.parseAsciiString("0n"));
assertEquals("99999999n", marshaller.toAsciiString(99999999L));
assertEquals(99999999L, (long) marshaller.parseAsciiString("99999999n"));
// micros
assertEquals("100000u", marshaller.toAsciiString(100000000L));
assertEquals(100000000L, (long) marshaller.parseAsciiString("100000u"));
assertEquals("99999999u", marshaller.toAsciiString(99999999999L));
assertEquals(99999999000L, (long) marshaller.parseAsciiString("99999999u"));
// millis
assertEquals("100000m", marshaller.toAsciiString(100000000000L));
assertEquals(100000000000L, (long) marshaller.parseAsciiString("100000m"));
assertEquals("99999999m", marshaller.toAsciiString(99999999999999L));
assertEquals(99999999000000L, (long) marshaller.parseAsciiString("99999999m"));
// seconds
assertEquals("100000S", marshaller.toAsciiString(100000000000000L));
assertEquals(100000000000000L, (long) marshaller.parseAsciiString("100000S"));
assertEquals("99999999S", marshaller.toAsciiString(99999999999999999L));
assertEquals(99999999000000000L, (long) marshaller.parseAsciiString("99999999S"));
// minutes
assertEquals("1666666M", marshaller.toAsciiString(100000000000000000L));
assertEquals(99999960000000000L, (long) marshaller.parseAsciiString("1666666M"));
assertEquals("99999999M", marshaller.toAsciiString(5999999999999999999L));
assertEquals(5999999940000000000L, (long) marshaller.parseAsciiString("99999999M"));
// hours
assertEquals("1666666H", marshaller.toAsciiString(6000000000000000000L));
assertEquals(5999997600000000000L, (long) marshaller.parseAsciiString("1666666H"));
assertEquals("2562047H", marshaller.toAsciiString(Long.MAX_VALUE));
assertEquals(9223369200000000000L, (long) marshaller.parseAsciiString("2562047H"));
assertEquals(Long.MAX_VALUE, (long) marshaller.parseAsciiString("2562048H"));
}
@Test
public void grpcUserAgent() {
assertTrue(GrpcUtil.getGrpcUserAgent("netty", null).startsWith("grpc-java-netty/"));
assertTrue(GrpcUtil.getGrpcUserAgent("okhttp", "libfoo/1.0")
.startsWith("libfoo/1.0 grpc-java-okhttp"));
}
@Test
public void contentTypeShouldBeValid() {
assertTrue(GrpcUtil.isGrpcContentType(GrpcUtil.CONTENT_TYPE_GRPC));
assertTrue(GrpcUtil.isGrpcContentType(GrpcUtil.CONTENT_TYPE_GRPC + "+blaa"));
assertTrue(GrpcUtil.isGrpcContentType(GrpcUtil.CONTENT_TYPE_GRPC + ";blaa"));
}
@Test
public void contentTypeShouldNotBeValid() {
assertFalse(GrpcUtil.isGrpcContentType("application/bad"));
}
@Test
public void checkAuthority_failsOnNull() {
thrown.expect(NullPointerException.class);
GrpcUtil.checkAuthority(null);
}
@Test
public void checkAuthority_succeedsOnHostAndPort() {
String actual = GrpcUtil.checkAuthority("valid:1234");
assertEquals("valid:1234", actual);
}
@Test
public void checkAuthority_succeedsOnHost() {
String actual = GrpcUtil.checkAuthority("valid");
assertEquals("valid", actual);
}
@Test
public void checkAuthority_succeedsOnIpV6() {
String actual = GrpcUtil.checkAuthority("[::1]");
assertEquals("[::1]", actual);
}
@Test
public void checkAuthority_failsOnInvalidAuthority() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Invalid authority");
GrpcUtil.checkAuthority("[ : : 1]");
}
@Test
public void checkAuthority_failsOnInvalidHost() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("No host in authority");
GrpcUtil.checkAuthority("bad_host");
}
@Test
public void checkAuthority_userInfoNotAllowed() {
thrown.expect(IllegalArgumentException.class);
thrown.expectMessage("Userinfo");
GrpcUtil.checkAuthority("foo@valid");
}
@Test
public void httpStatusToGrpcStatus_messageContainsHttpStatus() {
assertTrue(GrpcUtil.httpStatusToGrpcStatus(500).getDescription().contains("500"));
}
@Test
public void httpStatusToGrpcStatus_checkAgainstSpec() {
assertEquals(Status.Code.INTERNAL, GrpcUtil.httpStatusToGrpcStatus(400).getCode());
assertEquals(Status.Code.UNAUTHENTICATED, GrpcUtil.httpStatusToGrpcStatus(401).getCode());
assertEquals(Status.Code.PERMISSION_DENIED, GrpcUtil.httpStatusToGrpcStatus(403).getCode());
assertEquals(Status.Code.UNIMPLEMENTED, GrpcUtil.httpStatusToGrpcStatus(404).getCode());
assertEquals(Status.Code.UNAVAILABLE, GrpcUtil.httpStatusToGrpcStatus(429).getCode());
assertEquals(Status.Code.UNAVAILABLE, GrpcUtil.httpStatusToGrpcStatus(502).getCode());
assertEquals(Status.Code.UNAVAILABLE, GrpcUtil.httpStatusToGrpcStatus(503).getCode());
assertEquals(Status.Code.UNAVAILABLE, GrpcUtil.httpStatusToGrpcStatus(504).getCode());
// Some other code
assertEquals(Status.Code.UNKNOWN, GrpcUtil.httpStatusToGrpcStatus(500).getCode());
// If transport is doing it's job, 1xx should never happen. But it may not do its job.
assertEquals(Status.Code.INTERNAL, GrpcUtil.httpStatusToGrpcStatus(100).getCode());
assertEquals(Status.Code.INTERNAL, GrpcUtil.httpStatusToGrpcStatus(101).getCode());
}
@Test
public void httpStatusToGrpcStatus_neverOk() {
for (int i = -1; i < 800; i++) {
assertFalse(GrpcUtil.httpStatusToGrpcStatus(i).isOk());
}
}
@Test
public void getTransportFromPickResult_errorPickResult_waitForReady() {
Status status = Status.UNAVAILABLE;
PickResult pickResult = PickResult.withError(status);
ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult, true);
assertNull(transport);
}
@Test
public void getTransportFromPickResult_errorPickResult_failFast() {
Status status = Status.UNAVAILABLE;
PickResult pickResult = PickResult.withError(status);
ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult, false);
assertNotNull(transport);
ClientStream stream = transport
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
ClientStreamListener listener = mock(ClientStreamListener.class);
stream.start(listener);
verify(listener).closed(eq(status), eq(RpcProgress.PROCESSED), any(Metadata.class));
}
@Test
public void getTransportFromPickResult_dropPickResult_waitForReady() {
Status status = Status.UNAVAILABLE;
PickResult pickResult = PickResult.withDrop(status);
ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult, true);
assertNotNull(transport);
ClientStream stream = transport
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
ClientStreamListener listener = mock(ClientStreamListener.class);
stream.start(listener);
verify(listener).closed(eq(status), eq(RpcProgress.DROPPED), any(Metadata.class));
}
@Test
public void getTransportFromPickResult_dropPickResult_failFast() {
Status status = Status.UNAVAILABLE;
PickResult pickResult = PickResult.withDrop(status);
ClientTransport transport = GrpcUtil.getTransportFromPickResult(pickResult, false);
assertNotNull(transport);
ClientStream stream = transport
.newStream(TestMethodDescriptors.voidMethod(), new Metadata(), CallOptions.DEFAULT);
ClientStreamListener listener = mock(ClientStreamListener.class);
stream.start(listener);
verify(listener).closed(eq(status), eq(RpcProgress.DROPPED), any(Metadata.class));
}
}