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 <string>
6
7#include "base/files/file_path.h"
8#include "base/memory/singleton.h"
9#include "base/path_service.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/strings/string_piece.h"
12#include "net/tools/balsa/balsa_headers.h"
13#include "net/tools/quic/quic_in_memory_cache.h"
14#include "net/tools/quic/test_tools/quic_in_memory_cache_peer.h"
15#include "testing/gtest/include/gtest/gtest.h"
16
17using base::IntToString;
18using base::StringPiece;
19
20namespace net {
21namespace tools {
22namespace test {
23
24class QuicInMemoryCacheTest : public ::testing::Test {
25 protected:
26  QuicInMemoryCacheTest() {
27    base::FilePath path;
28    PathService::Get(base::DIR_SOURCE_ROOT, &path);
29    path = path.AppendASCII("net").AppendASCII("data")
30        .AppendASCII("quic_in_memory_cache_data");
31    // The file path is known to be an ascii string.
32    FLAGS_quic_in_memory_cache_dir = path.MaybeAsASCII();
33  }
34
35  void CreateRequest(std::string host,
36                     std::string path,
37                     net::BalsaHeaders* headers) {
38    headers->SetRequestFirstlineFromStringPieces("GET", path, "HTTP/1.1");
39    headers->ReplaceOrAppendHeader("host", host);
40  }
41
42  virtual void SetUp() OVERRIDE {
43    QuicInMemoryCachePeer::ResetForTests();
44  }
45
46  // This method was copied from end_to_end_test.cc in this directory.
47  void AddToCache(const StringPiece& method,
48                  const StringPiece& path,
49                  const StringPiece& version,
50                  const StringPiece& response_code,
51                  const StringPiece& response_detail,
52                  const StringPiece& body) {
53    BalsaHeaders request_headers, response_headers;
54    request_headers.SetRequestFirstlineFromStringPieces(method,
55                                                        path,
56                                                        version);
57    response_headers.SetRequestFirstlineFromStringPieces(version,
58                                                         response_code,
59                                                         response_detail);
60    response_headers.AppendHeader("content-length",
61                                  base::IntToString(body.length()));
62
63    // Check if response already exists and matches.
64    QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
65    const QuicInMemoryCache::Response* cached_response =
66        cache->GetResponse(request_headers);
67    if (cached_response != NULL) {
68      std::string cached_response_headers_str, response_headers_str;
69      cached_response->headers().DumpToString(&cached_response_headers_str);
70      response_headers.DumpToString(&response_headers_str);
71      CHECK_EQ(cached_response_headers_str, response_headers_str);
72      CHECK_EQ(cached_response->body(), body);
73      return;
74    }
75    cache->AddResponse(request_headers, response_headers, body);
76  }
77};
78
79TEST_F(QuicInMemoryCacheTest, AddResponseGetResponse) {
80  std::string response_body("hello response");
81  AddToCache("GET", "https://www.google.com/bar",
82             "HTTP/1.1", "200", "OK", response_body);
83  net::BalsaHeaders request_headers;
84  CreateRequest("www.google.com", "/bar", &request_headers);
85  QuicInMemoryCache* cache = QuicInMemoryCache::GetInstance();
86  const QuicInMemoryCache::Response* response =
87      cache->GetResponse(request_headers);
88  ASSERT_TRUE(response);
89  EXPECT_EQ("200", response->headers().response_code());
90  EXPECT_EQ(response_body.size(), response->body().length());
91
92  CreateRequest("", "https://www.google.com/bar", &request_headers);
93  response = cache->GetResponse(request_headers);
94  ASSERT_TRUE(response);
95  EXPECT_EQ("200", response->headers().response_code());
96  EXPECT_EQ(response_body.size(), response->body().length());
97}
98
99TEST_F(QuicInMemoryCacheTest, ReadsCacheDir) {
100  net::BalsaHeaders request_headers;
101  CreateRequest("quic.test.url", "/index.html", &request_headers);
102
103  const QuicInMemoryCache::Response* response =
104      QuicInMemoryCache::GetInstance()->GetResponse(request_headers);
105  ASSERT_TRUE(response);
106  std::string value;
107  response->headers().GetAllOfHeaderAsString("Connection", &value);
108  EXPECT_EQ("200", response->headers().response_code());
109  EXPECT_EQ("Keep-Alive", value);
110  EXPECT_LT(0U, response->body().length());
111}
112
113TEST_F(QuicInMemoryCacheTest, ReadsCacheDirHttp) {
114  net::BalsaHeaders request_headers;
115  CreateRequest("", "http://quic.test.url/index.html", &request_headers);
116
117  const QuicInMemoryCache::Response* response =
118      QuicInMemoryCache::GetInstance()->GetResponse(request_headers);
119  ASSERT_TRUE(response);
120  std::string value;
121  response->headers().GetAllOfHeaderAsString("Connection", &value);
122  EXPECT_EQ("200", response->headers().response_code());
123  EXPECT_EQ("Keep-Alive", value);
124  EXPECT_LT(0U, response->body().length());
125}
126
127TEST_F(QuicInMemoryCacheTest, GetResponseNoMatch) {
128  net::BalsaHeaders request_headers;
129  CreateRequest("www.google.com", "/index.html", &request_headers);
130
131  const QuicInMemoryCache::Response* response =
132      QuicInMemoryCache::GetInstance()->GetResponse(request_headers);
133  ASSERT_FALSE(response);
134}
135
136}  // namespace test
137}  // namespace tools
138}  // namespace net
139