blob: bab8f598b580be736c63a741db1fd9b45c8e96af [file] [log] [blame]
lryan56e307f2014-12-05 13:25:08 -08001/*
2 * Copyright 2014, Google Inc. All rights reserved.
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 *
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
nathanmittler29cbef12014-10-27 11:33:19 -070032package com.google.net.stubby.transport;
ejona913de472014-09-18 07:48:43 -070033
34import static org.junit.Assert.assertEquals;
35import static org.junit.Assert.assertTrue;
nathanmittler11c363a2015-01-09 11:22:19 -080036import static org.mockito.Matchers.anyInt;
ejona913de472014-09-18 07:48:43 -070037import static org.mockito.Matchers.eq;
nathanmittler11c363a2015-01-09 11:22:19 -080038import static org.mockito.Mockito.atLeastOnce;
ejona913de472014-09-18 07:48:43 -070039import static org.mockito.Mockito.mock;
40import static org.mockito.Mockito.verify;
41import static org.mockito.Mockito.verifyNoMoreInteractions;
ejona913de472014-09-18 07:48:43 -070042
43import com.google.common.io.ByteStreams;
44import com.google.common.primitives.Bytes;
simonmaf589a4a2015-01-15 16:23:32 -080045import com.google.net.stubby.transport.MessageDeframer.Listener;
ejona913de472014-09-18 07:48:43 -070046
47import org.junit.Test;
48import org.junit.runner.RunWith;
49import org.junit.runners.JUnit4;
50import org.mockito.ArgumentCaptor;
51
ejona913de472014-09-18 07:48:43 -070052import java.io.ByteArrayOutputStream;
53import java.io.IOException;
54import java.io.InputStream;
nathanmittler28fb46e2014-10-18 06:33:19 -070055import java.util.List;
56import java.util.zip.GZIPOutputStream;
ejona913de472014-09-18 07:48:43 -070057
58/**
simonmaf589a4a2015-01-15 16:23:32 -080059 * Tests for {@link MessageDeframer}.
ejona913de472014-09-18 07:48:43 -070060 */
61@RunWith(JUnit4.class)
simonmaf589a4a2015-01-15 16:23:32 -080062public class MessageDeframerTest {
nathanmittler11c363a2015-01-09 11:22:19 -080063 private Listener listener = mock(Listener.class);
nmittlerde3a1312015-01-16 11:54:24 -080064 private MessageDeframer deframer = new MessageDeframer(listener);
ejona913de472014-09-18 07:48:43 -070065 private ArgumentCaptor<InputStream> messages = ArgumentCaptor.forClass(InputStream.class);
66
67 @Test
68 public void simplePayload() {
nmittlerde3a1312015-01-16 11:54:24 -080069 deframer.request(1);
70 deframer.deframe(buffer(new byte[]{0, 0, 0, 0, 2, 3, 14}), false);
nathanmittler11c363a2015-01-09 11:22:19 -080071 verify(listener).messageRead(messages.capture(), eq(2));
72 assertEquals(Bytes.asList(new byte[]{3, 14}), bytes(messages));
73 verify(listener, atLeastOnce()).bytesRead(anyInt());
74 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -070075 }
76
77 @Test
78 public void smallCombinedPayloads() {
nmittlerde3a1312015-01-16 11:54:24 -080079 deframer.request(2);
80 deframer.deframe(buffer(new byte[]{0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 2, 14, 15}), false);
nathanmittler11c363a2015-01-09 11:22:19 -080081 verify(listener).messageRead(messages.capture(), eq(1));
ejona913de472014-09-18 07:48:43 -070082 assertEquals(Bytes.asList(new byte[] {3}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -080083 verify(listener).messageRead(messages.capture(), eq(2));
84 verify(listener, atLeastOnce()).bytesRead(anyInt());
ejona913de472014-09-18 07:48:43 -070085 assertEquals(Bytes.asList(new byte[] {14, 15}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -080086 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -070087 }
88
89 @Test
ejona9d502992014-09-22 12:23:19 -070090 public void endOfStreamWithPayloadShouldNotifyEndOfStream() {
nmittlerde3a1312015-01-16 11:54:24 -080091 deframer.request(1);
92 deframer.deframe(buffer(new byte[] {0, 0, 0, 0, 1, 3}), true);
nathanmittler11c363a2015-01-09 11:22:19 -080093 verify(listener).messageRead(messages.capture(), eq(1));
ejona913de472014-09-18 07:48:43 -070094 assertEquals(Bytes.asList(new byte[] {3}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -080095 verify(listener).endOfStream();
96 verify(listener, atLeastOnce()).bytesRead(anyInt());
97 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -070098 }
99
100 @Test
ejona9d502992014-09-22 12:23:19 -0700101 public void endOfStreamShouldNotifyEndOfStream() {
nmittlerde3a1312015-01-16 11:54:24 -0800102 deframer.deframe(buffer(new byte[0]), true);
nathanmittler11c363a2015-01-09 11:22:19 -0800103 verify(listener).endOfStream();
104 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700105 }
106
107 @Test
108 public void payloadSplitBetweenBuffers() {
nmittlerde3a1312015-01-16 11:54:24 -0800109 deframer.request(1);
110 deframer.deframe(buffer(new byte[] {0, 0, 0, 0, 7, 3, 14, 1, 5, 9}), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800111 verify(listener, atLeastOnce()).bytesRead(anyInt());
112 verifyNoMoreInteractions(listener);
nmittlerde3a1312015-01-16 11:54:24 -0800113 deframer.deframe(buffer(new byte[] {2, 6}), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800114 verify(listener).messageRead(messages.capture(), eq(7));
ejona913de472014-09-18 07:48:43 -0700115 assertEquals(Bytes.asList(new byte[] {3, 14, 1, 5, 9, 2, 6}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800116 verify(listener, atLeastOnce()).bytesRead(anyInt());
117 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700118 }
119
120 @Test
121 public void frameHeaderSplitBetweenBuffers() {
nmittlerde3a1312015-01-16 11:54:24 -0800122 deframer.request(1);
123
124 deframer.deframe(buffer(new byte[] {0, 0}), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800125 verify(listener, atLeastOnce()).bytesRead(anyInt());
126 verifyNoMoreInteractions(listener);
nmittlerde3a1312015-01-16 11:54:24 -0800127 deframer.deframe(buffer(new byte[] {0, 0, 1, 3}), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800128 verify(listener).messageRead(messages.capture(), eq(1));
ejona913de472014-09-18 07:48:43 -0700129 assertEquals(Bytes.asList(new byte[] {3}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800130 verify(listener, atLeastOnce()).bytesRead(anyInt());
131 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700132 }
133
134 @Test
135 public void emptyPayload() {
nmittlerde3a1312015-01-16 11:54:24 -0800136 deframer.request(1);
137 deframer.deframe(buffer(new byte[] {0, 0, 0, 0, 0}), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800138 verify(listener).messageRead(messages.capture(), eq(0));
ejona913de472014-09-18 07:48:43 -0700139 assertEquals(Bytes.asList(), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800140 verify(listener, atLeastOnce()).bytesRead(anyInt());
141 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700142 }
143
144 @Test
145 public void largerFrameSize() {
nmittlerde3a1312015-01-16 11:54:24 -0800146 deframer.request(1);
147 deframer.deframe(
148 Buffers.wrap(Bytes.concat(new byte[] {0, 0, 0, 3, (byte) 232}, new byte[1000])), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800149 verify(listener).messageRead(messages.capture(), eq(1000));
ejona913de472014-09-18 07:48:43 -0700150 assertEquals(Bytes.asList(new byte[1000]), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800151 verify(listener, atLeastOnce()).bytesRead(anyInt());
152 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700153 }
154
155 @Test
nmittlerde3a1312015-01-16 11:54:24 -0800156 public void endOfStreamCallbackShouldWaitForMessageDelivery() {
157 deframer.deframe(buffer(new byte[] {0, 0, 0, 0, 1, 3}), true);
nathanmittler11c363a2015-01-09 11:22:19 -0800158 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700159
nmittlerde3a1312015-01-16 11:54:24 -0800160 deframer.request(1);
nathanmittler11c363a2015-01-09 11:22:19 -0800161 verify(listener).messageRead(messages.capture(), eq(1));
ejona913de472014-09-18 07:48:43 -0700162 assertEquals(Bytes.asList(new byte[] {3}), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800163 verify(listener).endOfStream();
164 verify(listener, atLeastOnce()).bytesRead(anyInt());
165 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700166 }
167
168 @Test
169 public void compressed() {
nmittlerde3a1312015-01-16 11:54:24 -0800170 deframer = new MessageDeframer(listener, MessageDeframer.Compression.GZIP);
171 deframer.request(1);
172
ejona913de472014-09-18 07:48:43 -0700173 byte[] payload = compress(new byte[1000]);
174 assertTrue(payload.length < 100);
175 byte[] header = new byte[] {1, 0, 0, 0, (byte) payload.length};
176 deframer.deframe(buffer(Bytes.concat(header, payload)), false);
nathanmittler11c363a2015-01-09 11:22:19 -0800177 verify(listener).messageRead(messages.capture(), eq(1000));
ejona913de472014-09-18 07:48:43 -0700178 assertEquals(Bytes.asList(new byte[1000]), bytes(messages));
nathanmittler11c363a2015-01-09 11:22:19 -0800179 verify(listener, atLeastOnce()).bytesRead(anyInt());
180 verifyNoMoreInteractions(listener);
ejona913de472014-09-18 07:48:43 -0700181 }
182
183 private static List<Byte> bytes(ArgumentCaptor<InputStream> captor) {
184 try {
185 return Bytes.asList(ByteStreams.toByteArray(captor.getValue()));
186 } catch (IOException ex) {
187 throw new AssertionError(ex);
188 }
189 }
190
191 private static Buffer buffer(byte[] bytes) {
192 return Buffers.wrap(bytes);
193 }
194
195 private static byte[] compress(byte[] bytes) {
196 try {
197 ByteArrayOutputStream baos = new ByteArrayOutputStream();
198 GZIPOutputStream zip = new GZIPOutputStream(baos);
199 zip.write(bytes);
200 zip.close();
201 return baos.toByteArray();
202 } catch (IOException ex) {
203 throw new RuntimeException(ex);
204 }
205 }
206}