From 661376a6c1eb3bd501398f225363c2d021288245 Mon Sep 17 00:00:00 2001
From: "hclam@chromium.org"
 <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>
Date: Wed, 29 Apr 2009 02:04:23 +0000
Subject: Supports single range request with file protocol Added range request
 support in URLRequestFileJob to respect "Range" HTTP header. Fail with
 ERR_REQUESTED_RANGE_NOT_SATISFIABLE if range is bad. The following range
 request modes are supported: 1. Fully specified: bytes=x-y 2. With first byte
 position only: bytes=x- 3. With suffix length: bytes=-y

Multiple ranges in a single request is not supported as we need to multipart
encoding..

Last review was here: http://codereview.chromium.org/92149

Review URL: http://codereview.chromium.org/102006

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@14817 0039d316-1c4b-4281-b951-d872f2087c98
---
 net/url_request/url_request_unittest.cc | 135 +++++++++++++++++++++++++++++++-
 1 file changed, 134 insertions(+), 1 deletion(-)

(limited to 'net/url_request/url_request_unittest.cc')

diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 86b5b9c..eb67a94 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
@@ -83,6 +83,21 @@ bool ContainsString(const std::string& haystack, const char* needle) {
   return it != haystack.end();
 }
 
+void FillBuffer(char* buffer, size_t len) {
+  static bool called = false;
+  if (!called) {
+    called = true;
+    int seed = static_cast<int>(Time::Now().ToInternalValue());
+    srand(seed);
+  }
+
+  for (size_t i = 0; i < len; i++) {
+    buffer[i] = static_cast<char>(rand());
+    if (!buffer[i])
+      buffer[i] = 'g';
+  }
+}
+
 }  // namespace
 
 // Inherit PlatformTest since we require the autorelease pool on Mac OS X.f
@@ -613,6 +628,124 @@ TEST_F(URLRequestTest, FileTest) {
 #endif
 }
 
+TEST_F(URLRequestTest, FileTestFullSpecifiedRange) {
+  const size_t buffer_size = 4000;
+  scoped_array<char> buffer(new char[buffer_size]);
+  FillBuffer(buffer.get(), buffer_size);
+
+  FilePath temp_path;
+  EXPECT_TRUE(file_util::CreateTemporaryFileName(&temp_path));
+  GURL temp_url = net::FilePathToFileURL(temp_path);
+  file_util::WriteFile(temp_path, buffer.get(), buffer_size);
+
+  int64 file_size;
+  EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+
+  const size_t first_byte_position = 500;
+  const size_t last_byte_position = buffer_size - first_byte_position;
+  const size_t content_length = last_byte_position - first_byte_position + 1;
+  std::string partial_buffer_string(buffer.get() + first_byte_position,
+                                    buffer.get() + last_byte_position + 1);
+
+  TestDelegate d;
+  {
+    TestURLRequest r(temp_url, &d);
+
+    r.SetExtraRequestHeaders(StringPrintf("Range: bytes=%d-%d\n",
+                                          first_byte_position,
+                                          last_byte_position));
+    r.Start();
+    EXPECT_TRUE(r.is_pending());
+
+    MessageLoop::current()->Run();
+    EXPECT_TRUE(!r.is_pending());
+    EXPECT_EQ(1, d.response_started_count());
+    EXPECT_FALSE(d.received_data_before_response());
+    EXPECT_EQ(static_cast<int>(content_length), d.bytes_received());
+    // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
+    EXPECT_TRUE(partial_buffer_string == d.data_received());
+  }
+
+  EXPECT_TRUE(file_util::Delete(temp_path, false));
+#ifndef NDEBUG
+  DCHECK_EQ(url_request_metrics.object_count, 0);
+#endif
+}
+
+TEST_F(URLRequestTest, FileTestHalfSpecifiedRange) {
+  const size_t buffer_size = 4000;
+  scoped_array<char> buffer(new char[buffer_size]);
+  FillBuffer(buffer.get(), buffer_size);
+
+  FilePath temp_path;
+  EXPECT_TRUE(file_util::CreateTemporaryFileName(&temp_path));
+  GURL temp_url = net::FilePathToFileURL(temp_path);
+  file_util::WriteFile(temp_path, buffer.get(), buffer_size);
+
+  int64 file_size;
+  EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+
+  const size_t first_byte_position = 500;
+  const size_t last_byte_position = buffer_size - 1;
+  const size_t content_length = last_byte_position - first_byte_position + 1;
+  std::string partial_buffer_string(buffer.get() + first_byte_position,
+                                    buffer.get() + last_byte_position + 1);
+
+  TestDelegate d;
+  {
+    TestURLRequest r(temp_url, &d);
+
+    r.SetExtraRequestHeaders(StringPrintf("Range: bytes=%d-\n",
+                                          first_byte_position));
+    r.Start();
+    EXPECT_TRUE(r.is_pending());
+
+    MessageLoop::current()->Run();
+    EXPECT_TRUE(!r.is_pending());
+    EXPECT_EQ(1, d.response_started_count());
+    EXPECT_FALSE(d.received_data_before_response());
+    EXPECT_EQ(static_cast<int>(content_length), d.bytes_received());
+    // Don't use EXPECT_EQ, it will print out a lot of garbage if check failed.
+    EXPECT_TRUE(partial_buffer_string == d.data_received());
+  }
+
+  EXPECT_TRUE(file_util::Delete(temp_path, false));
+#ifndef NDEBUG
+  DCHECK_EQ(url_request_metrics.object_count, 0);
+#endif
+}
+
+TEST_F(URLRequestTest, FileTestMultipleRanges) {
+  const size_t buffer_size = 400000;
+  scoped_array<char> buffer(new char[buffer_size]);
+  FillBuffer(buffer.get(), buffer_size);
+
+  FilePath temp_path;
+  EXPECT_TRUE(file_util::CreateTemporaryFileName(&temp_path));
+  GURL temp_url = net::FilePathToFileURL(temp_path);
+  file_util::WriteFile(temp_path, buffer.get(), buffer_size);
+
+  int64 file_size;
+  EXPECT_TRUE(file_util::GetFileSize(temp_path, &file_size));
+
+  TestDelegate d;
+  {
+    TestURLRequest r(temp_url, &d);
+
+    r.SetExtraRequestHeaders(StringPrintf("Range: bytes=0-0,10-200,200-300\n"));
+    r.Start();
+    EXPECT_TRUE(r.is_pending());
+
+    MessageLoop::current()->Run();
+    EXPECT_TRUE(d.request_failed());
+  }
+
+  EXPECT_TRUE(file_util::Delete(temp_path, false));
+#ifndef NDEBUG
+  DCHECK_EQ(url_request_metrics.object_count, 0);
+#endif
+}
+
 TEST_F(URLRequestTest, InvalidUrlTest) {
   TestDelegate d;
   {
-- 
cgit v1.1