blob: e8266f44181b1dd0d44262060d9e12db90208df0 [file] [log] [blame]
// Copyright 2014 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.
#include "net/url_request/url_fetcher_response_writer.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_scoped_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/platform_test.h"
using net::test::IsOk;
namespace net {
namespace {
const char kData[] = "Hello!";
} // namespace
class URLFetcherStringWriterTest : public PlatformTest {
protected:
void SetUp() override {
writer_.reset(new URLFetcherStringWriter);
buf_ = base::MakeRefCounted<StringIOBuffer>(kData);
}
std::unique_ptr<URLFetcherStringWriter> writer_;
scoped_refptr<StringIOBuffer> buf_;
};
TEST_F(URLFetcherStringWriterTest, Basic) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
EXPECT_EQ(kData, writer_->data());
// Initialize() again to reset.
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
EXPECT_TRUE(writer_->data().empty());
}
#if defined(STARBOARD)
class URLFetcherLargeStringWriterTest : public PlatformTest {
protected:
void SetUp() override {
writer_.reset(new URLFetcherLargeStringWriter);
buf_ = base::MakeRefCounted<StringIOBuffer>(kData);
}
std::unique_ptr<URLFetcherLargeStringWriter> writer_;
scoped_refptr<StringIOBuffer> buf_;
};
TEST_F(URLFetcherLargeStringWriterTest, Basic) {
// The structure of this case is copied from URLFetcherStringWriterTest.Basic.
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
std::string actual_data;
writer_->GetAndResetData(&actual_data);
// TODO(b/158043520): as requested by yuying@, we should add a test that uses
// a string that is actually large as the test data.
EXPECT_EQ(kData, actual_data);
// Initialize() again to reset.
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
writer_->GetAndResetData(&actual_data);
EXPECT_TRUE(actual_data.empty());
}
TEST_F(URLFetcherLargeStringWriterTest, OnResponseStartedPreallocatesMemory) {
int rv = 0;
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Should be larger than the default string size but otherwise arbitrary.
int64_t content_length = 1234;
writer_->OnResponseStarted(content_length);
std::string actual_data;
writer_->GetAndResetData(&actual_data);
EXPECT_GE(actual_data.capacity(), content_length);
}
#endif
class URLFetcherFileWriterTest : public PlatformTest,
public WithScopedTaskEnvironment {
protected:
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
file_path_ = temp_dir_.GetPath().AppendASCII("test.txt");
writer_.reset(new URLFetcherFileWriter(base::ThreadTaskRunnerHandle::Get(),
file_path_));
buf_ = base::MakeRefCounted<StringIOBuffer>(kData);
}
base::ScopedTempDir temp_dir_;
base::FilePath file_path_;
std::unique_ptr<URLFetcherFileWriter> writer_;
scoped_refptr<StringIOBuffer> buf_;
};
TEST_F(URLFetcherFileWriterTest, WriteToFile) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
EXPECT_EQ(file_path_.value(), writer_->file_path().value());
std::string file_contents;
EXPECT_TRUE(base::ReadFileToString(writer_->file_path(), &file_contents));
EXPECT_EQ(kData, file_contents);
// Destroy the writer. File should be deleted.
writer_.reset();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(file_path_));
}
TEST_F(URLFetcherFileWriterTest, InitializeAgain) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
std::string file_contents;
EXPECT_TRUE(base::ReadFileToString(writer_->file_path(), &file_contents));
EXPECT_EQ(kData, file_contents);
// Initialize() again to reset. Write different data.
const std::string data2 = "Bye!";
scoped_refptr<StringIOBuffer> buf2 =
base::MakeRefCounted<StringIOBuffer>(data2);
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf2.get(), buf2->size(), callback.callback());
EXPECT_EQ(buf2->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
file_contents.clear();
EXPECT_TRUE(base::ReadFileToString(writer_->file_path(), &file_contents));
EXPECT_EQ(data2, file_contents);
}
TEST_F(URLFetcherFileWriterTest, FinishWhileWritePending) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_THAT(callback.WaitForResult(), IsOk());
TestCompletionCallback callback2;
rv = writer_->Write(buf_.get(), buf_->size(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestCompletionCallback callback3;
rv = writer_->Finish(ERR_FAILED, callback3.callback());
EXPECT_EQ(OK, rv);
base::RunLoop().RunUntilIdle();
// Verify the result.
EXPECT_FALSE(base::PathExists(file_path_));
}
TEST_F(URLFetcherFileWriterTest, FinishWhileOpenPending) {
int rv = 0;
// Initialize() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestCompletionCallback callback2;
rv = writer_->Finish(ERR_FAILED, callback2.callback());
EXPECT_EQ(OK, rv);
base::RunLoop().RunUntilIdle();
// Verify the result.
EXPECT_FALSE(base::PathExists(file_path_));
}
TEST_F(URLFetcherFileWriterTest, InitializeAgainAfterFinishWithError) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_THAT(callback.WaitForResult(), IsOk());
TestCompletionCallback callback2;
rv = writer_->Write(buf_.get(), buf_->size(), callback2.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
TestCompletionCallback callback3;
rv = writer_->Finish(ERR_FAILED, callback3.callback());
EXPECT_EQ(OK, rv);
base::RunLoop().RunUntilIdle();
// Initialize() again and wait for it to complete.
TestCompletionCallback callback4;
rv = writer_->Initialize(callback4.callback());
EXPECT_EQ(ERR_IO_PENDING, rv);
EXPECT_THAT(callback4.WaitForResult(), IsOk());
// Verify the result.
EXPECT_TRUE(base::PathExists(file_path_));
}
TEST_F(URLFetcherFileWriterTest, DisownFile) {
int rv = 0;
// Initialize() and Finish() to create a file.
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Disown file.
writer_->DisownFile();
// File is not deleted even after the writer gets destroyed.
writer_.reset();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(base::PathExists(file_path_));
}
class URLFetcherFileWriterTemporaryFileTest : public PlatformTest,
public WithScopedTaskEnvironment {
protected:
void SetUp() override {
writer_.reset(new URLFetcherFileWriter(base::ThreadTaskRunnerHandle::Get(),
base::FilePath()));
buf_ = base::MakeRefCounted<StringIOBuffer>(kData);
}
std::unique_ptr<URLFetcherFileWriter> writer_;
scoped_refptr<StringIOBuffer> buf_;
};
TEST_F(URLFetcherFileWriterTemporaryFileTest, WriteToTemporaryFile) {
int rv = 0;
// Initialize(), Write() and Finish().
TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result.
std::string file_contents;
EXPECT_TRUE(base::ReadFileToString(writer_->file_path(), &file_contents));
EXPECT_EQ(kData, file_contents);
// Destroy the writer. File should be deleted.
const base::FilePath file_path = writer_->file_path();
writer_.reset();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(base::PathExists(file_path));
}
} // namespace net