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