1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_buffer.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <cstddef>
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include <cstring>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/basictypes.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/bind.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/io_buffer.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/spdy/spdy_protocol.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kData[] = "hello!\0hi.";
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kDataSize = arraysize(kData);
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class SpdyBufferTest : public ::testing::Test {};
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Make a string from the data remaining in |buffer|.
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string BufferToString(const SpdyBuffer& buffer) {
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string(buffer.GetRemainingData(), buffer.GetRemainingSize());
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Construct a SpdyBuffer from a SpdyFrame and make sure its data
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// points to the frame's underlying data.
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpdyBufferTest, FrameConstructor) {
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyBuffer buffer(
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      scoped_ptr<SpdyFrame>(
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          new SpdyFrame(const_cast<char*>(kData), kDataSize,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        false /* owns_buffer */)));
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kData, buffer.GetRemainingData());
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kDataSize, buffer.GetRemainingSize());
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Construct a SpdyBuffer from a const char*/size_t pair and make sure
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// it makes a copy of the data.
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpdyBufferTest, DataConstructor) {
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string data(kData, kDataSize);
49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyBuffer buffer(data.data(), data.size());
50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This mutation shouldn't affect |buffer|'s data.
51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  data[0] = 'H';
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_NE(kData, buffer.GetRemainingData());
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kDataSize, buffer.GetRemainingSize());
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kData, kDataSize), BufferToString(buffer));
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void IncrementBy(size_t* x,
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SpdyBuffer::ConsumeSource expected_consume_source,
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 size_t delta,
61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                 SpdyBuffer::ConsumeSource consume_source) {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(expected_consume_source, consume_source);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  *x += delta;
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Construct a SpdyBuffer and call Consume() on it, which should
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// update the remaining data pointer and size appropriately, as well
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// as calling the consume callbacks.
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpdyBufferTest, Consume) {
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyBuffer buffer(kData, kDataSize);
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t x1 = 0;
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t x2 = 0;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.AddConsumeCallback(
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&IncrementBy, &x1, SpdyBuffer::CONSUME));
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.AddConsumeCallback(
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::Bind(&IncrementBy, &x2, SpdyBuffer::CONSUME));
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kData, kDataSize), BufferToString(buffer));
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.Consume(5);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(std::string(kData + 5, kDataSize - 5), BufferToString(buffer));
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(5u, x1);
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(5u, x2);
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.Consume(kDataSize - 5);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(0u, buffer.GetRemainingSize());
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kDataSize, x1);
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kDataSize, x2);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Construct a SpdyBuffer and attach a ConsumeCallback to it. The
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// callback should be called when the SpdyBuffer is destroyed.
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpdyBufferTest, ConsumeOnDestruction) {
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t x = 0;
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  {
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    SpdyBuffer buffer(kData, kDataSize);
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    buffer.AddConsumeCallback(
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&IncrementBy, &x, SpdyBuffer::DISCARD));
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(kDataSize, x);
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Make sure the IOBuffer returned by GetIOBufferForRemainingData()
107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// points to the buffer's remaining data and isn't updated by
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Consume().
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)TEST_F(SpdyBufferTest, GetIOBufferForRemainingData) {
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SpdyBuffer buffer(kData, kDataSize);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.Consume(5);
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_refptr<IOBuffer> io_buffer = buffer.GetIOBufferForRemainingData();
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  size_t io_buffer_size = buffer.GetRemainingSize();
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const std::string expectedData(kData + 5, kDataSize - 5);
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(expectedData, std::string(io_buffer->data(), io_buffer_size));
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  buffer.Consume(kDataSize - 5);
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  EXPECT_EQ(expectedData, std::string(io_buffer->data(), io_buffer_size));
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Make sure the IOBuffer returned by GetIOBufferForRemainingData()
1237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// outlives the buffer itself.
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochTEST_F(SpdyBufferTest, IOBufferForRemainingDataOutlivesBuffer) {
1257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_ptr<SpdyBuffer> buffer(new SpdyBuffer(kData, kDataSize));
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scoped_refptr<IOBuffer> io_buffer = buffer->GetIOBufferForRemainingData();
1287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  buffer.reset();
1297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // This will cause a use-after-free error if |io_buffer| doesn't
1317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // outlive |buffer|.
1327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::memcpy(io_buffer->data(), kData, kDataSize);
1337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
1347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
138