Home | History | Annotate | Download | only in websockets
      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.get());
     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.get());
     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.get());
     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.get()));
     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).get());
     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.get());
    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.get());
    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.get());
    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.get());
    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.get());
    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.get());
    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