/* * Copyright 2016, Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package io.grpc.netty; import static io.grpc.internal.GrpcUtil.DEFAULT_MAX_HEADER_LIST_SIZE; import static io.netty.util.AsciiString.of; import static org.hamcrest.CoreMatchers.containsString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import io.grpc.netty.GrpcHttp2HeadersDecoder.GrpcHttp2ClientHeadersDecoder; import io.grpc.netty.GrpcHttp2HeadersDecoder.GrpcHttp2ServerHeadersDecoder; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.handler.codec.http2.DefaultHttp2Headers; import io.netty.handler.codec.http2.DefaultHttp2HeadersEncoder; import io.netty.handler.codec.http2.Http2Exception; import io.netty.handler.codec.http2.Http2Headers; import io.netty.handler.codec.http2.Http2HeadersDecoder; import io.netty.handler.codec.http2.Http2HeadersEncoder; import io.netty.handler.codec.http2.Http2HeadersEncoder.SensitivityDetector; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** * Tests for {@link GrpcHttp2HeadersDecoder}. */ @RunWith(JUnit4.class) public class GrpcHttp2HeadersDecoderTest { private static final SensitivityDetector NEVER_SENSITIVE = new SensitivityDetector() { @Override public boolean isSensitive(CharSequence name, CharSequence value) { return false; } }; private ByteBuf encodedHeaders; @After public void tearDown() { if (encodedHeaders != null) { encodedHeaders.release(); } } @Test public void decode_requestHeaders() throws Http2Exception { Http2HeadersDecoder decoder = new GrpcHttp2ServerHeadersDecoder(DEFAULT_MAX_HEADER_LIST_SIZE); Http2HeadersEncoder encoder = new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE); Http2Headers headers = new DefaultHttp2Headers(false); headers.add(of(":scheme"), of("https")).add(of(":method"), of("GET")) .add(of(":path"), of("index.html")).add(of(":authority"), of("foo.grpc.io")) .add(of("custom"), of("header")); encodedHeaders = Unpooled.buffer(); encoder.encodeHeaders(1 /* randomly chosen */, headers, encodedHeaders); Http2Headers decodedHeaders = decoder.decodeHeaders(3 /* randomly chosen */, encodedHeaders); assertEquals(headers.get(of(":scheme")), decodedHeaders.scheme()); assertEquals(headers.get(of(":method")), decodedHeaders.method()); assertEquals(headers.get(of(":path")), decodedHeaders.path()); assertEquals(headers.get(of(":authority")), decodedHeaders.authority()); assertEquals(headers.get(of("custom")), decodedHeaders.get(of("custom"))); assertEquals(headers.size(), decodedHeaders.size()); String toString = decodedHeaders.toString(); assertContainsKeyAndValue(toString, ":scheme", decodedHeaders.scheme()); assertContainsKeyAndValue(toString, ":method", decodedHeaders.method()); assertContainsKeyAndValue(toString, ":path", decodedHeaders.path()); assertContainsKeyAndValue(toString, ":authority", decodedHeaders.authority()); assertContainsKeyAndValue(toString, "custom", decodedHeaders.get(of("custom"))); } @Test public void decode_responseHeaders() throws Http2Exception { Http2HeadersDecoder decoder = new GrpcHttp2ClientHeadersDecoder(DEFAULT_MAX_HEADER_LIST_SIZE); Http2HeadersEncoder encoder = new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE); Http2Headers headers = new DefaultHttp2Headers(false); headers.add(of(":status"), of("200")).add(of("custom"), of("header")); encodedHeaders = Unpooled.buffer(); encoder.encodeHeaders(1 /* randomly chosen */, headers, encodedHeaders); Http2Headers decodedHeaders = decoder.decodeHeaders(3 /* randomly chosen */, encodedHeaders); assertEquals(headers.get(of(":status")), decodedHeaders.get(of(":status"))); assertEquals(headers.get(of("custom")), decodedHeaders.get(of("custom"))); assertEquals(headers.size(), decodedHeaders.size()); String toString = decodedHeaders.toString(); assertContainsKeyAndValue(toString, ":status", decodedHeaders.get(of(":status"))); assertContainsKeyAndValue(toString, "custom", decodedHeaders.get(of("custom"))); } @Test public void decode_emptyHeaders() throws Http2Exception { Http2HeadersDecoder decoder = new GrpcHttp2ClientHeadersDecoder(8192); Http2HeadersEncoder encoder = new DefaultHttp2HeadersEncoder(NEVER_SENSITIVE); ByteBuf encodedHeaders = Unpooled.buffer(); encoder.encodeHeaders(1 /* randomly chosen */, new DefaultHttp2Headers(false), encodedHeaders); Http2Headers decodedHeaders = decoder.decodeHeaders(3 /* randomly chosen */, encodedHeaders); assertEquals(0, decodedHeaders.size()); assertThat(decodedHeaders.toString(), containsString("[]")); } private static void assertContainsKeyAndValue(String str, CharSequence key, CharSequence value) { assertThat(str, containsString(key.toString())); assertThat(str, containsString(value.toString())); } }