blob: 197ab7597b14baad44f63253d42e5d17fa94cd51 [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 http dump fetcher, using a mock fetcher. Note that
// the HTTP Dump Fetcher is, in essence, a caching fetcher except that:
// 1. It ignores caching headers completely
// 2. It uses file-based storage with no expectation of ever evicting
// anything.
//
// TODO(jmarantz): consider making this class a special case of the
// combination of HTTPCache, FileCache, and HttpDumpUrlFetcher.
#include "net/instaweb/http/public/http_dump_url_fetcher.h"
#include "net/instaweb/http/public/async_fetch.h"
#include "net/instaweb/http/public/request_context.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/google_message_handler.h"
#include "pagespeed/kernel/base/gtest.h"
#include "pagespeed/kernel/base/mock_timer.h"
#include "pagespeed/kernel/base/stdio_file_system.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/base/timer.h"
#include "pagespeed/kernel/http/http_names.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/util/platform.h"
namespace net_instaweb {
namespace {
class HttpDumpUrlFetcherTest : public testing::Test {
public:
HttpDumpUrlFetcherTest()
: thread_system_(Platform::CreateThreadSystem()),
mock_timer_(thread_system_->NewMutex(), 0),
http_dump_fetcher_(
GTestSrcDir() + "/net/instaweb/http/testdata",
&file_system_,
&mock_timer_) {
}
protected:
scoped_ptr<ThreadSystem> thread_system_;
MockTimer mock_timer_;
StdioFileSystem file_system_;
GoogleString content_;
HttpDumpUrlFetcher http_dump_fetcher_;
GoogleMessageHandler message_handler_;
private:
DISALLOW_COPY_AND_ASSIGN(HttpDumpUrlFetcherTest);
};
TEST_F(HttpDumpUrlFetcherTest, TestReadWithGzip) {
ResponseHeaders response;
RequestHeaders request;
request.Add(HttpAttributes::kAcceptEncoding, HttpAttributes::kGzip);
StringAsyncFetch fetch(
RequestContext::NewTestRequestContext(thread_system_.get()), &content_);
fetch.set_response_headers(&response);
fetch.set_request_headers(&request);
http_dump_fetcher_.Fetch(
"http://www.google.com", &message_handler_, &fetch);
ASSERT_TRUE(fetch.done());
ASSERT_TRUE(fetch.success());
ConstStringStarVector v;
ASSERT_TRUE(response.Lookup(HttpAttributes::kContentEncoding, &v));
ASSERT_EQ(1, v.size());
EXPECT_EQ(GoogleString(HttpAttributes::kGzip), *(v[0]));
EXPECT_EQ(5513, content_.size());
v.clear();
ASSERT_TRUE(response.Lookup(HttpAttributes::kContentLength, &v));
ASSERT_EQ(1, v.size());
EXPECT_EQ(GoogleString("5513"), *(v[0]));
}
TEST_F(HttpDumpUrlFetcherTest, TestReadUncompressedFromGzippedDump) {
ResponseHeaders response;
StringAsyncFetch fetch(
RequestContext::NewTestRequestContext(thread_system_.get()), &content_);
fetch.set_response_headers(&response);
http_dump_fetcher_.Fetch(
"http://www.google.com", &message_handler_, &fetch);
ASSERT_TRUE(fetch.done());
ASSERT_TRUE(fetch.success());
ConstStringStarVector v;
if (response.Lookup(HttpAttributes::kContentEncoding, &v)) {
ASSERT_EQ(1, v.size());
EXPECT_NE(GoogleString(HttpAttributes::kGzip), *(v[0]));
}
EXPECT_EQ(14450, content_.size());
v.clear();
ASSERT_TRUE(response.Lookup(HttpAttributes::kContentLength, &v));
ASSERT_EQ(1, v.size());
EXPECT_EQ(GoogleString("14450"), *(v[0]));
}
// Helper that checks the Date: field as it starts writing.
class CheckDateHeaderFetch : public StringAsyncFetch {
public:
CheckDateHeaderFetch(const MockTimer* timer, ThreadSystem* threads)
: StringAsyncFetch(RequestContext::NewTestRequestContext(threads)),
headers_complete_called_(false), timer_(timer) {}
virtual ~CheckDateHeaderFetch() {}
virtual void HandleHeadersComplete() {
headers_complete_called_ = true;
response_headers()->ComputeCaching();
EXPECT_EQ(timer_->NowMs(), response_headers()->date_ms());
}
bool headers_complete_called() const { return headers_complete_called_; }
private:
bool headers_complete_called_;
const MockTimer* timer_;
DISALLOW_COPY_AND_ASSIGN(CheckDateHeaderFetch);
};
TEST_F(HttpDumpUrlFetcherTest, TestDateAdjustment) {
// Set a time in 2030s, which should be bigger than the time of the slurp,
// which is a prerequisite for date adjustment
mock_timer_.SetTimeUs(60 * Timer::kYearMs * Timer::kMsUs);
// Make sure that date fixing up works in time for first write ---
// which is needed for adapting it into an async fetcher.
CheckDateHeaderFetch check_date(&mock_timer_, thread_system_.get());
http_dump_fetcher_.Fetch("http://www.google.com", &message_handler_,
&check_date);
EXPECT_TRUE(check_date.done());
EXPECT_TRUE(check_date.success());
EXPECT_TRUE(check_date.headers_complete_called());
}
} // namespace
} // namespace net_instaweb