Commit ee63375d authored by xunjieli's avatar xunjieli Committed by Commit bot

Make URLFetcherFileWriter::Finish() skip closing file when there is an error

This CL makes URLFetcherFileWriter::Finish() skip closing file when there is an
error. If there is an error, Finish() will delete the file after any pending
operation completes.

TBR=hashimoto@chromium.org
TBR=mkwst@chromium.org
BUG=487732, 656692

Review-Url: https://chromiumcodereview.appspot.com/2425673006
Cr-Commit-Position: refs/heads/master@{#426540}
parent b6e73773
...@@ -249,7 +249,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter { ...@@ -249,7 +249,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter {
int Write(net::IOBuffer* buffer, int Write(net::IOBuffer* buffer,
int num_bytes, int num_bytes,
const net::CompletionCallback& callback) override; const net::CompletionCallback& callback) override;
int Finish(const net::CompletionCallback& callback) override; int Finish(int net_error, const net::CompletionCallback& callback) override;
private: private:
base::WeakPtr<DevToolsUIBindings> bindings_; base::WeakPtr<DevToolsUIBindings> bindings_;
...@@ -293,7 +293,8 @@ int ResponseWriter::Write(net::IOBuffer* buffer, ...@@ -293,7 +293,8 @@ int ResponseWriter::Write(net::IOBuffer* buffer,
return num_bytes; return num_bytes;
} }
int ResponseWriter::Finish(const net::CompletionCallback& callback) { int ResponseWriter::Finish(int net_error,
const net::CompletionCallback& callback) {
return net::OK; return net::OK;
} }
......
...@@ -156,7 +156,7 @@ class URLFetcherNullWriter : public net::URLFetcherResponseWriter { ...@@ -156,7 +156,7 @@ class URLFetcherNullWriter : public net::URLFetcherResponseWriter {
return num_bytes; return num_bytes;
} }
int Finish(const net::CompletionCallback& callback) override { int Finish(int net_error, const net::CompletionCallback& callback) override {
return net::OK; return net::OK;
} }
}; };
......
...@@ -49,7 +49,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter { ...@@ -49,7 +49,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter {
int Write(net::IOBuffer* buffer, int Write(net::IOBuffer* buffer,
int num_bytes, int num_bytes,
const net::CompletionCallback& callback) override; const net::CompletionCallback& callback) override;
int Finish(const net::CompletionCallback& callback) override; int Finish(int net_error, const net::CompletionCallback& callback) override;
private: private:
base::WeakPtr<ShellDevToolsFrontend> shell_devtools_; base::WeakPtr<ShellDevToolsFrontend> shell_devtools_;
...@@ -90,7 +90,8 @@ int ResponseWriter::Write(net::IOBuffer* buffer, ...@@ -90,7 +90,8 @@ int ResponseWriter::Write(net::IOBuffer* buffer,
return num_bytes; return num_bytes;
} }
int ResponseWriter::Finish(const net::CompletionCallback& callback) { int ResponseWriter::Finish(int net_error,
const net::CompletionCallback& callback) {
return net::OK; return net::OK;
} }
......
...@@ -312,9 +312,10 @@ int ResponseWriter::Write(net::IOBuffer* buffer, ...@@ -312,9 +312,10 @@ int ResponseWriter::Write(net::IOBuffer* buffer,
return num_bytes; return num_bytes;
} }
int ResponseWriter::Finish(const net::CompletionCallback& callback) { int ResponseWriter::Finish(int net_error,
const net::CompletionCallback& callback) {
if (file_writer_) if (file_writer_)
return file_writer_->Finish(callback); return file_writer_->Finish(net_error, callback);
return net::OK; return net::OK;
} }
......
...@@ -135,7 +135,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter { ...@@ -135,7 +135,7 @@ class ResponseWriter : public net::URLFetcherResponseWriter {
int Write(net::IOBuffer* buffer, int Write(net::IOBuffer* buffer,
int num_bytes, int num_bytes,
const net::CompletionCallback& callback) override; const net::CompletionCallback& callback) override;
int Finish(const net::CompletionCallback& callback) override; int Finish(int net_error, const net::CompletionCallback& callback) override;
private: private:
void DidWrite(scoped_refptr<net::IOBuffer> buffer, void DidWrite(scoped_refptr<net::IOBuffer> buffer,
......
...@@ -188,7 +188,7 @@ void TestURLFetcher::SaveResponseWithWriter( ...@@ -188,7 +188,7 @@ void TestURLFetcher::SaveResponseWithWriter(
fake_response_string_.size(), fake_response_string_.size(),
CompletionCallback()); CompletionCallback());
DCHECK_EQ(static_cast<int>(fake_response_string_.size()), response); DCHECK_EQ(static_cast<int>(fake_response_string_.size()), response);
response = response_writer_->Finish(CompletionCallback()); response = response_writer_->Finish(OK, CompletionCallback());
DCHECK_EQ(OK, response); DCHECK_EQ(OK, response);
} else if (fake_response_destination_ == TEMP_FILE) { } else if (fake_response_destination_ == TEMP_FILE) {
// SaveResponseToFileAtPath() should be called instead of this method to // SaveResponseToFileAtPath() should be called instead of this method to
......
...@@ -477,6 +477,7 @@ void URLFetcherCore::OnReadCompleted(URLRequest* request, ...@@ -477,6 +477,7 @@ void URLFetcherCore::OnReadCompleted(URLRequest* request,
// No more data to write. // No more data to write.
const int result = response_writer_->Finish( const int result = response_writer_->Finish(
bytes_read > 0 ? OK : bytes_read,
base::Bind(&URLFetcherCore::DidFinishWriting, this)); base::Bind(&URLFetcherCore::DidFinishWriting, this));
if (result != ERR_IO_PENDING) if (result != ERR_IO_PENDING)
DidFinishWriting(result); DidFinishWriting(result);
...@@ -861,7 +862,7 @@ int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) { ...@@ -861,7 +862,7 @@ int URLFetcherCore::WriteBuffer(scoped_refptr<DrainableIOBuffer> data) {
void URLFetcherCore::DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data, void URLFetcherCore::DidWriteBuffer(scoped_refptr<DrainableIOBuffer> data,
int result) { int result) {
if (result < 0) { // Handle errors. if (result < 0) { // Handle errors.
response_writer_->Finish(base::Bind(&EmptyCompletionCallback)); response_writer_->Finish(result, base::Bind(&EmptyCompletionCallback));
CancelRequestAndInformDelegate(result); CancelRequestAndInformDelegate(result);
return; return;
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "net/url_request/url_fetcher_response_writer.h" #include "net/url_request/url_fetcher_response_writer.h"
#include "base/callback_helpers.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/location.h" #include "base/location.h"
#include "base/sequenced_task_runner.h" #include "base/sequenced_task_runner.h"
...@@ -40,7 +41,8 @@ int URLFetcherStringWriter::Write(IOBuffer* buffer, ...@@ -40,7 +41,8 @@ int URLFetcherStringWriter::Write(IOBuffer* buffer,
return num_bytes; return num_bytes;
} }
int URLFetcherStringWriter::Finish(const CompletionCallback& callback) { int URLFetcherStringWriter::Finish(int net_error,
const CompletionCallback& callback) {
// Do nothing. // Do nothing.
return OK; return OK;
} }
...@@ -64,9 +66,12 @@ URLFetcherFileWriter::~URLFetcherFileWriter() { ...@@ -64,9 +66,12 @@ URLFetcherFileWriter::~URLFetcherFileWriter() {
} }
int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) { int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
DCHECK(!callback_);
file_stream_.reset(new FileStream(file_task_runner_)); file_stream_.reset(new FileStream(file_task_runner_));
int result = ERR_IO_PENDING; int result = ERR_IO_PENDING;
owns_file_ = true;
if (file_path_.empty()) { if (file_path_.empty()) {
base::FilePath* temp_file_path = new base::FilePath; base::FilePath* temp_file_path = new base::FilePath;
base::PostTaskAndReplyWithResult( base::PostTaskAndReplyWithResult(
...@@ -75,18 +80,22 @@ int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) { ...@@ -75,18 +80,22 @@ int URLFetcherFileWriter::Initialize(const CompletionCallback& callback) {
base::Bind(&base::CreateTemporaryFile, temp_file_path), base::Bind(&base::CreateTemporaryFile, temp_file_path),
base::Bind(&URLFetcherFileWriter::DidCreateTempFile, base::Bind(&URLFetcherFileWriter::DidCreateTempFile,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(),
callback,
base::Owned(temp_file_path))); base::Owned(temp_file_path)));
} else { } else {
result = file_stream_->Open( result = file_stream_->Open(file_path_, base::File::FLAG_WRITE |
file_path_, base::File::FLAG_ASYNC |
base::File::FLAG_WRITE | base::File::FLAG_ASYNC |
base::File::FLAG_CREATE_ALWAYS, base::File::FLAG_CREATE_ALWAYS,
base::Bind(&URLFetcherFileWriter::DidOpenFile, base::Bind(&URLFetcherFileWriter::OnIOCompleted,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr()));
callback));
DCHECK_NE(OK, result); DCHECK_NE(OK, result);
} }
if (result == ERR_IO_PENDING) {
callback_ = callback;
return result;
}
if (result < 0)
CloseAndDeleteFile();
return result; return result;
} }
...@@ -95,24 +104,43 @@ int URLFetcherFileWriter::Write(IOBuffer* buffer, ...@@ -95,24 +104,43 @@ int URLFetcherFileWriter::Write(IOBuffer* buffer,
const CompletionCallback& callback) { const CompletionCallback& callback) {
DCHECK(file_stream_); DCHECK(file_stream_);
DCHECK(owns_file_); DCHECK(owns_file_);
DCHECK(!callback_);
int result = file_stream_->Write(buffer, num_bytes, int result = file_stream_->Write(
base::Bind(&URLFetcherFileWriter::DidWrite, buffer, num_bytes, base::Bind(&URLFetcherFileWriter::OnIOCompleted,
weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr()));
callback)); if (result == ERR_IO_PENDING) {
if (result < 0 && result != ERR_IO_PENDING) callback_ = callback;
return result;
}
if (result < 0)
CloseAndDeleteFile(); CloseAndDeleteFile();
return result; return result;
} }
int URLFetcherFileWriter::Finish(const CompletionCallback& callback) { int URLFetcherFileWriter::Finish(int net_error,
const CompletionCallback& callback) {
DCHECK_NE(ERR_IO_PENDING, net_error);
// If an error occurred, simply delete the file after any pending operation
// is done. Do not call file_stream_->Close() because there might be an
// operation pending. See crbug.com/487732.
if (net_error < 0) {
// Cancel callback and invalid weak ptrs so as to cancel any posted task.
callback_.Reset();
weak_factory_.InvalidateWeakPtrs();
CloseAndDeleteFile();
return OK;
}
DCHECK(!callback_);
// If the file_stream_ still exists at this point, close it. // If the file_stream_ still exists at this point, close it.
if (file_stream_) { if (file_stream_) {
int result = file_stream_->Close(base::Bind( int result = file_stream_->Close(base::Bind(
&URLFetcherFileWriter::CloseComplete, &URLFetcherFileWriter::CloseComplete, weak_factory_.GetWeakPtr()));
weak_factory_.GetWeakPtr(), callback)); if (result == ERR_IO_PENDING) {
if (result != ERR_IO_PENDING) callback_ = callback;
return result;
}
file_stream_.reset(); file_stream_.reset();
return result; return result;
} }
...@@ -131,14 +159,6 @@ void URLFetcherFileWriter::DisownFile() { ...@@ -131,14 +159,6 @@ void URLFetcherFileWriter::DisownFile() {
owns_file_ = false; owns_file_ = false;
} }
void URLFetcherFileWriter::DidWrite(const CompletionCallback& callback,
int result) {
if (result < 0)
CloseAndDeleteFile();
callback.Run(result);
}
void URLFetcherFileWriter::CloseAndDeleteFile() { void URLFetcherFileWriter::CloseAndDeleteFile() {
if (!owns_file_) if (!owns_file_)
return; return;
...@@ -151,41 +171,35 @@ void URLFetcherFileWriter::CloseAndDeleteFile() { ...@@ -151,41 +171,35 @@ void URLFetcherFileWriter::CloseAndDeleteFile() {
false /* recursive */)); false /* recursive */));
} }
void URLFetcherFileWriter::DidCreateTempFile(const CompletionCallback& callback, void URLFetcherFileWriter::DidCreateTempFile(base::FilePath* temp_file_path,
base::FilePath* temp_file_path,
bool success) { bool success) {
if (!success) { if (!success) {
callback.Run(ERR_FILE_NOT_FOUND); OnIOCompleted(ERR_FILE_NOT_FOUND);
return; return;
} }
file_path_ = *temp_file_path; file_path_ = *temp_file_path;
owns_file_ = true;
const int result = file_stream_->Open( const int result = file_stream_->Open(
file_path_, file_path_,
base::File::FLAG_WRITE | base::File::FLAG_ASYNC | base::File::FLAG_WRITE | base::File::FLAG_ASYNC | base::File::FLAG_OPEN,
base::File::FLAG_OPEN, base::Bind(&URLFetcherFileWriter::OnIOCompleted,
base::Bind(&URLFetcherFileWriter::DidOpenFile, weak_factory_.GetWeakPtr()));
weak_factory_.GetWeakPtr(),
callback));
if (result != ERR_IO_PENDING) if (result != ERR_IO_PENDING)
DidOpenFile(callback, result); OnIOCompleted(result);
} }
void URLFetcherFileWriter::DidOpenFile(const CompletionCallback& callback, void URLFetcherFileWriter::OnIOCompleted(int result) {
int result) { if (result < OK)
if (result == OK)
owns_file_ = true;
else
CloseAndDeleteFile(); CloseAndDeleteFile();
callback.Run(result); if (!callback_.is_null())
base::ResetAndReturn(&callback_).Run(result);
} }
void URLFetcherFileWriter::CloseComplete(const CompletionCallback& callback, void URLFetcherFileWriter::CloseComplete(int result) {
int result) {
// Destroy |file_stream_| whether or not the close succeeded. // Destroy |file_stream_| whether or not the close succeeded.
file_stream_.reset(); file_stream_.reset();
callback.Run(result); if (!callback_.is_null())
base::ResetAndReturn(&callback_).Run(result);
} }
} // namespace net } // namespace net
...@@ -45,9 +45,14 @@ class NET_EXPORT URLFetcherResponseWriter { ...@@ -45,9 +45,14 @@ class NET_EXPORT URLFetcherResponseWriter {
int num_bytes, int num_bytes,
const CompletionCallback& callback) = 0; const CompletionCallback& callback) = 0;
// Finishes writing. If ERR_IO_PENDING is returned, |callback| will be run // Finishes writing. If |net_error| is not OK, this method can be called
// later with the result. // in the middle of another operation (eg. Initialize() and Write()). On
virtual int Finish(const CompletionCallback& callback) = 0; // errors (|net_error| not OK), this method may be called before the previous
// operation completed. In this case, URLFetcherResponseWriter may skip
// graceful shutdown and completion of the pending operation. After such a
// failure, the URLFetcherResponseWriter may be reused. If ERR_IO_PENDING is
// returned, |callback| will be run later with the result.
virtual int Finish(int net_error, const CompletionCallback& callback) = 0;
// Returns this instance's pointer as URLFetcherStringWriter when possible. // Returns this instance's pointer as URLFetcherStringWriter when possible.
virtual URLFetcherStringWriter* AsStringWriter(); virtual URLFetcherStringWriter* AsStringWriter();
...@@ -69,7 +74,7 @@ class NET_EXPORT URLFetcherStringWriter : public URLFetcherResponseWriter { ...@@ -69,7 +74,7 @@ class NET_EXPORT URLFetcherStringWriter : public URLFetcherResponseWriter {
int Write(IOBuffer* buffer, int Write(IOBuffer* buffer,
int num_bytes, int num_bytes,
const CompletionCallback& callback) override; const CompletionCallback& callback) override;
int Finish(const CompletionCallback& callback) override; int Finish(int net_error, const CompletionCallback& callback) override;
URLFetcherStringWriter* AsStringWriter() override; URLFetcherStringWriter* AsStringWriter() override;
private: private:
...@@ -95,7 +100,7 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter { ...@@ -95,7 +100,7 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter {
int Write(IOBuffer* buffer, int Write(IOBuffer* buffer,
int num_bytes, int num_bytes,
const CompletionCallback& callback) override; const CompletionCallback& callback) override;
int Finish(const CompletionCallback& callback) override; int Finish(int net_error, const CompletionCallback& callback) override;
URLFetcherFileWriter* AsFileWriter() override; URLFetcherFileWriter* AsFileWriter() override;
// Drops ownership of the file at |file_path_|. // Drops ownership of the file at |file_path_|.
...@@ -103,23 +108,18 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter { ...@@ -103,23 +108,18 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter {
void DisownFile(); void DisownFile();
private: private:
// Called when a write has been done.
void DidWrite(const CompletionCallback& callback, int result);
// Closes the file if it is open and then delete it. // Closes the file if it is open and then delete it.
void CloseAndDeleteFile(); void CloseAndDeleteFile();
// Callback which gets the result of a temporary file creation. // Callback which gets the result of a temporary file creation.
void DidCreateTempFile(const CompletionCallback& callback, void DidCreateTempFile(base::FilePath* temp_file_path, bool success);
base::FilePath* temp_file_path,
bool success);
// Callback which gets the result of FileStream::Open. // Run |callback_| if it is non-null when FileStream::Open or
void DidOpenFile(const CompletionCallback& callback, // FileStream::Write is completed.
int result); void OnIOCompleted(int result);
// Callback which gets the result of closing a file. // Callback which gets the result of closing a file.
void CloseComplete(const CompletionCallback& callback, int result); void CloseComplete(int result);
// Task runner on which file operations should happen. // Task runner on which file operations should happen.
scoped_refptr<base::SequencedTaskRunner> file_task_runner_; scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
...@@ -133,6 +133,8 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter { ...@@ -133,6 +133,8 @@ class NET_EXPORT URLFetcherFileWriter : public URLFetcherResponseWriter {
std::unique_ptr<FileStream> file_stream_; std::unique_ptr<FileStream> file_stream_;
CompletionCallback callback_;
// Callbacks are created for use with base::FileUtilProxy. // Callbacks are created for use with base::FileUtilProxy.
base::WeakPtrFactory<URLFetcherFileWriter> weak_factory_; base::WeakPtrFactory<URLFetcherFileWriter> weak_factory_;
......
...@@ -44,7 +44,7 @@ TEST_F(URLFetcherStringWriterTest, Basic) { ...@@ -44,7 +44,7 @@ TEST_F(URLFetcherStringWriterTest, Basic) {
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback()); rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv)); EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result. // Verify the result.
...@@ -80,7 +80,7 @@ TEST_F(URLFetcherFileWriterTest, WriteToFile) { ...@@ -80,7 +80,7 @@ TEST_F(URLFetcherFileWriterTest, WriteToFile) {
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback()); rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv)); EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result. // Verify the result.
...@@ -103,7 +103,7 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) { ...@@ -103,7 +103,7 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) {
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback()); rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv)); EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result. // Verify the result.
...@@ -119,7 +119,7 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) { ...@@ -119,7 +119,7 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) {
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf2.get(), buf2->size(), callback.callback()); rv = writer_->Write(buf2.get(), buf2->size(), callback.callback());
EXPECT_EQ(buf2->size(), callback.GetResult(rv)); EXPECT_EQ(buf2->size(), callback.GetResult(rv));
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result. // Verify the result.
...@@ -128,13 +128,71 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) { ...@@ -128,13 +128,71 @@ TEST_F(URLFetcherFileWriterTest, InitializeAgain) {
EXPECT_EQ(data2, 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) { TEST_F(URLFetcherFileWriterTest, DisownFile) {
int rv = 0; int rv = 0;
// Initialize() and Finish() to create a file. // Initialize() and Finish() to create a file.
TestCompletionCallback callback; TestCompletionCallback callback;
rv = writer_->Initialize(callback.callback()); rv = writer_->Initialize(callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Disown file. // Disown file.
...@@ -166,7 +224,7 @@ TEST_F(URLFetcherFileWriterTemporaryFileTest, WriteToTemporaryFile) { ...@@ -166,7 +224,7 @@ TEST_F(URLFetcherFileWriterTemporaryFileTest, WriteToTemporaryFile) {
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
rv = writer_->Write(buf_.get(), buf_->size(), callback.callback()); rv = writer_->Write(buf_.get(), buf_->size(), callback.callback());
EXPECT_EQ(buf_->size(), callback.GetResult(rv)); EXPECT_EQ(buf_->size(), callback.GetResult(rv));
rv = writer_->Finish(callback.callback()); rv = writer_->Finish(OK, callback.callback());
EXPECT_THAT(callback.GetResult(rv), IsOk()); EXPECT_THAT(callback.GetResult(rv), IsOk());
// Verify the result. // Verify the result.
......
...@@ -40,7 +40,8 @@ class UnownedStringWriter : public net::URLFetcherResponseWriter { ...@@ -40,7 +40,8 @@ class UnownedStringWriter : public net::URLFetcherResponseWriter {
return num_bytes; return num_bytes;
} }
virtual int Finish(const net::CompletionCallback& callback) override { virtual int Finish(int net_error,
const net::CompletionCallback& callback) override {
return net::OK; return net::OK;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment