blob: 4a8c90cf95c9cfecb01b7dbf39ee368e8a1cc5d6 [file] [log] [blame]
/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmarantz@google.com (Joshua Marantz)
// Unit-test the lru cache
#include "net/instaweb/util/public/http_value.h"
#include "base/basictypes.h"
#include "base/logging.h"
#include "net/instaweb/util/public/google_message_handler.h"
#include <string>
#include "net/instaweb/util/public/string_util.h"
#include "net/instaweb/util/public/gtest.h"
#include "net/instaweb/util/public/shared_string.h"
#include "net/instaweb/util/public/simple_meta_data.h"
namespace {
const int kMaxSize = 100;
}
namespace net_instaweb {
class HTTPValueTest : public testing::Test {
protected:
HTTPValueTest() { }
void FillMetaData(MetaData* meta_data) {
meta_data->SetStatusAndReason(HttpStatus::kOK);
meta_data->set_major_version(1);
meta_data->set_minor_version(0);
meta_data->set_reason_phrase("OK");
meta_data->Add("Cache-control", "public, max-age=300");
}
void CheckMetaData(const MetaData& meta_data) {
SimpleMetaData expected;
FillMetaData(&expected);
EXPECT_EQ(expected.ToString(), meta_data.ToString());
}
GoogleMessageHandler message_handler_;
private:
DISALLOW_COPY_AND_ASSIGN(HTTPValueTest);
};
TEST_F(HTTPValueTest, Empty) {
HTTPValue value;
EXPECT_TRUE(value.Empty());
}
TEST_F(HTTPValueTest, HeadersFirst) {
HTTPValue value;
SimpleMetaData headers, check_headers;
FillMetaData(&headers);
value.SetHeaders(headers);
value.Write("body", &message_handler_);
StringPiece body;
ASSERT_TRUE(value.ExtractContents(&body));
EXPECT_EQ("body", body.as_string());
ASSERT_TRUE(value.ExtractHeaders(&check_headers, &message_handler_));
CheckMetaData(check_headers);
}
TEST_F(HTTPValueTest, ContentsFirst) {
HTTPValue value;
SimpleMetaData headers, check_headers;
FillMetaData(&headers);
value.Write("body", &message_handler_);
value.SetHeaders(headers);
StringPiece body;
ASSERT_TRUE(value.ExtractContents(&body));
EXPECT_EQ("body", body.as_string());
ASSERT_TRUE(value.ExtractHeaders(&check_headers, &message_handler_));
CheckMetaData(check_headers);
}
TEST_F(HTTPValueTest, EmptyContentsFirst) {
HTTPValue value;
SimpleMetaData headers, check_headers;
FillMetaData(&headers);
value.Write("", &message_handler_);
value.SetHeaders(headers);
StringPiece body;
ASSERT_TRUE(value.ExtractContents(&body));
EXPECT_EQ("", body.as_string());
ASSERT_TRUE(value.ExtractHeaders(&check_headers, &message_handler_));
CheckMetaData(check_headers);
}
TEST_F(HTTPValueTest, TestCopyOnWrite) {
HTTPValue v1;
v1.Write("Hello", &message_handler_);
StringPiece v1_contents, v2_contents, v3_contents;
ASSERT_TRUE(v1.ExtractContents(&v1_contents));
EXPECT_TRUE(v1.unique());
// Now check that copy-construction shares the buffer.
HTTPValue v2(v1);
EXPECT_FALSE(v1.unique());
EXPECT_FALSE(v2.unique());
ASSERT_TRUE(v2.ExtractContents(&v2_contents));
EXPECT_EQ(v1_contents, v2_contents);
EXPECT_EQ(v1_contents.data(), v2_contents.data()); // buffer sharing
// Also the assignment operator should induce sharing.
HTTPValue v3 = v1;
EXPECT_FALSE(v3.unique());
ASSERT_TRUE(v3.ExtractContents(&v3_contents));
EXPECT_EQ(v1_contents, v3_contents);
EXPECT_EQ(v1_contents.data(), v3_contents.data()); // buffer sharing
// Now write something into v1. Due to copy-on-write semantics, v2 and
// will v3 not see it.
v1.Write(", World!", &message_handler_);
ASSERT_TRUE(v1.ExtractContents(&v1_contents));
ASSERT_TRUE(v2.ExtractContents(&v2_contents));
ASSERT_TRUE(v3.ExtractContents(&v3_contents));
EXPECT_EQ("Hello, World!", v1_contents);
EXPECT_NE(v1_contents, v2_contents);
EXPECT_NE(v1_contents.data(), v2_contents.data()); // no buffer sharing
EXPECT_NE(v1_contents, v3_contents);
EXPECT_NE(v1_contents.data(), v3_contents.data()); // no buffer sharing
// But v2 and v3 will remain connected to one another
EXPECT_EQ(v2_contents, v3_contents);
EXPECT_EQ(v2_contents.data(), v3_contents.data()); // buffer sharing
}
TEST_F(HTTPValueTest, TestShare) {
SharedString storage;
{
HTTPValue value;
SimpleMetaData headers, check_headers;
FillMetaData(&headers);
value.SetHeaders(headers);
value.Write("body", &message_handler_);
storage = *value.share();
}
{
HTTPValue value;
SimpleMetaData check_headers;
ASSERT_TRUE(value.Link(&storage, &check_headers, &message_handler_));
StringPiece body;
ASSERT_TRUE(value.ExtractContents(&body));
EXPECT_EQ("body", body.as_string());
CheckMetaData(check_headers);
}
}
TEST_F(HTTPValueTest, LinkEmpty) {
SharedString storage;
HTTPValue value;
SimpleMetaData headers;
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
}
TEST_F(HTTPValueTest, LinkCorrupt) {
SharedString storage("h");
HTTPValue value;
SimpleMetaData headers;
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
storage->append("9999");
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
storage->append("xyz");
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
*storage = "b";
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
storage->append("9999");
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
storage->append("xyz");
ASSERT_FALSE(value.Link(&storage, &headers, &message_handler_));
}
} // namespace net_instaweb