1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "net/websockets/websocket_inflater.h" 6 7 #include <stdint.h> 8 #include <string> 9 #include <vector> 10 11 #include "base/memory/ref_counted.h" 12 #include "net/base/io_buffer.h" 13 #include "net/websockets/websocket_deflater.h" 14 #include "net/websockets/websocket_test_util.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace net { 18 19 namespace { 20 21 std::string ToString(IOBufferWithSize* buffer) { 22 return std::string(buffer->data(), buffer->size()); 23 } 24 25 TEST(WebSocketInflaterTest, Construct) { 26 WebSocketInflater inflater; 27 ASSERT_TRUE(inflater.Initialize(15)); 28 29 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 30 } 31 32 TEST(WebSocketInflaterTest, InflateHelloTakeOverContext) { 33 WebSocketInflater inflater; 34 ASSERT_TRUE(inflater.Initialize(15)); 35 scoped_refptr<IOBufferWithSize> actual1, actual2; 36 37 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 38 ASSERT_TRUE(inflater.Finish()); 39 actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); 40 ASSERT_TRUE(actual1); 41 EXPECT_EQ("Hello", ToString(actual1.get())); 42 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 43 44 ASSERT_TRUE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5)); 45 ASSERT_TRUE(inflater.Finish()); 46 actual2 = inflater.GetOutput(inflater.CurrentOutputSize()); 47 ASSERT_TRUE(actual2); 48 EXPECT_EQ("Hello", ToString(actual2.get())); 49 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 50 } 51 52 TEST(WebSocketInflaterTest, InflateHelloSmallCapacity) { 53 WebSocketInflater inflater(1, 1); 54 ASSERT_TRUE(inflater.Initialize(15)); 55 std::string actual; 56 57 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 58 ASSERT_TRUE(inflater.Finish()); 59 for (size_t i = 0; i < 5; ++i) { 60 ASSERT_EQ(1u, inflater.CurrentOutputSize()); 61 scoped_refptr<IOBufferWithSize> buffer = inflater.GetOutput(1); 62 ASSERT_TRUE(buffer); 63 ASSERT_EQ(1, buffer->size()); 64 actual += ToString(buffer.get()); 65 } 66 EXPECT_EQ("Hello", actual); 67 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 68 } 69 70 TEST(WebSocketInflaterTest, InflateHelloSmallCapacityGetTotalOutput) { 71 WebSocketInflater inflater(1, 1); 72 ASSERT_TRUE(inflater.Initialize(15)); 73 scoped_refptr<IOBufferWithSize> actual; 74 75 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 76 ASSERT_TRUE(inflater.Finish()); 77 ASSERT_EQ(1u, inflater.CurrentOutputSize()); 78 actual = inflater.GetOutput(1024); 79 EXPECT_EQ("Hello", ToString(actual)); 80 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 81 } 82 83 TEST(WebSocketInflaterTest, InflateInvalidData) { 84 WebSocketInflater inflater; 85 ASSERT_TRUE(inflater.Initialize(15)); 86 EXPECT_FALSE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16)); 87 } 88 89 TEST(WebSocketInflaterTest, ChokedInvalidData) { 90 WebSocketInflater inflater(1, 1); 91 ASSERT_TRUE(inflater.Initialize(15)); 92 93 EXPECT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9INVALID DATA", 16)); 94 EXPECT_TRUE(inflater.Finish()); 95 EXPECT_EQ(1u, inflater.CurrentOutputSize()); 96 EXPECT_FALSE(inflater.GetOutput(1024)); 97 } 98 99 TEST(WebSocketInflaterTest, MultipleAddBytesCalls) { 100 WebSocketInflater inflater; 101 ASSERT_TRUE(inflater.Initialize(15)); 102 std::string input("\xf2\x48\xcd\xc9\xc9\x07\x00", 7); 103 scoped_refptr<IOBufferWithSize> actual; 104 105 for (size_t i = 0; i < input.size(); ++i) { 106 ASSERT_TRUE(inflater.AddBytes(&input[i], 1)); 107 } 108 ASSERT_TRUE(inflater.Finish()); 109 actual = inflater.GetOutput(5); 110 ASSERT_TRUE(actual); 111 EXPECT_EQ("Hello", ToString(actual.get())); 112 } 113 114 TEST(WebSocketInflaterTest, Reset) { 115 WebSocketInflater inflater; 116 ASSERT_TRUE(inflater.Initialize(15)); 117 scoped_refptr<IOBufferWithSize> actual1, actual2; 118 119 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 120 ASSERT_TRUE(inflater.Finish()); 121 actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); 122 ASSERT_TRUE(actual1); 123 EXPECT_EQ("Hello", ToString(actual1.get())); 124 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 125 126 // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0] 127 ASSERT_TRUE(inflater.AddBytes("\x01", 1)); 128 ASSERT_TRUE(inflater.Finish()); 129 ASSERT_EQ(0u, inflater.CurrentOutputSize()); 130 131 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 132 ASSERT_TRUE(inflater.Finish()); 133 actual2 = inflater.GetOutput(inflater.CurrentOutputSize()); 134 ASSERT_TRUE(actual2); 135 EXPECT_EQ("Hello", ToString(actual2.get())); 136 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 137 } 138 139 TEST(WebSocketInflaterTest, ResetAndLostContext) { 140 WebSocketInflater inflater; 141 scoped_refptr<IOBufferWithSize> actual1, actual2; 142 ASSERT_TRUE(inflater.Initialize(15)); 143 144 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 145 ASSERT_TRUE(inflater.Finish()); 146 actual1 = inflater.GetOutput(inflater.CurrentOutputSize()); 147 ASSERT_TRUE(actual1); 148 EXPECT_EQ("Hello", ToString(actual1.get())); 149 EXPECT_EQ(0u, inflater.CurrentOutputSize()); 150 151 // Reset the stream with a block [BFINAL = 1, BTYPE = 00, LEN = 0] 152 ASSERT_TRUE(inflater.AddBytes("\x01", 1)); 153 ASSERT_TRUE(inflater.Finish()); 154 ASSERT_EQ(0u, inflater.CurrentOutputSize()); 155 156 // The context is already reset. 157 ASSERT_FALSE(inflater.AddBytes("\xf2\x00\x11\x00\x00", 5)); 158 } 159 160 TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutput) { 161 WebSocketInflater inflater; 162 scoped_refptr<IOBufferWithSize> actual1, actual2; 163 ASSERT_TRUE(inflater.Initialize(15)); 164 165 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 166 ASSERT_TRUE(inflater.Finish()); 167 EXPECT_EQ(5u, inflater.CurrentOutputSize()); 168 169 // This is a test for detecting memory leaks with valgrind. 170 } 171 172 TEST(WebSocketInflaterTest, CallAddBytesAndFinishWithoutGetOutputChoked) { 173 WebSocketInflater inflater(1, 1); 174 scoped_refptr<IOBufferWithSize> actual1, actual2; 175 ASSERT_TRUE(inflater.Initialize(15)); 176 177 ASSERT_TRUE(inflater.AddBytes("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); 178 ASSERT_TRUE(inflater.Finish()); 179 EXPECT_EQ(1u, inflater.CurrentOutputSize()); 180 181 // This is a test for detecting memory leaks with valgrind. 182 } 183 184 TEST(WebSocketInflaterTest, LargeRandomDeflateInflate) { 185 const size_t size = 64 * 1024; 186 LinearCongruentialGenerator generator(133); 187 std::vector<char> input; 188 std::vector<char> output; 189 scoped_refptr<IOBufferWithSize> compressed; 190 191 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); 192 ASSERT_TRUE(deflater.Initialize(8)); 193 WebSocketInflater inflater(256, 256); 194 ASSERT_TRUE(inflater.Initialize(8)); 195 196 for (size_t i = 0; i < size; ++i) 197 input.push_back(static_cast<char>(generator.Generate())); 198 199 ASSERT_TRUE(deflater.AddBytes(&input[0], input.size())); 200 ASSERT_TRUE(deflater.Finish()); 201 202 compressed = deflater.GetOutput(deflater.CurrentOutputSize()); 203 204 ASSERT_TRUE(compressed); 205 ASSERT_EQ(0u, deflater.CurrentOutputSize()); 206 207 ASSERT_TRUE(inflater.AddBytes(compressed->data(), compressed->size())); 208 ASSERT_TRUE(inflater.Finish()); 209 210 while (inflater.CurrentOutputSize() > 0) { 211 scoped_refptr<IOBufferWithSize> uncompressed = 212 inflater.GetOutput(inflater.CurrentOutputSize()); 213 ASSERT_TRUE(uncompressed); 214 output.insert(output.end(), 215 uncompressed->data(), 216 uncompressed->data() + uncompressed->size()); 217 } 218 219 EXPECT_EQ(output, input); 220 } 221 222 } // unnamed namespace 223 224 } // namespace net 225