blob: 0e9472c3c6123b020b48154a3cc04229eb984bd8 [file] [log] [blame]
// Copyright (c) 2012 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 "google_apis/drive/base_requests.h"
#include <stdint.h>
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "google_apis/drive/drive_api_parser.h"
#include "google_apis/drive/drive_api_requests.h"
#include "google_apis/drive/dummy_auth_service.h"
#include "google_apis/drive/request_sender.h"
#include "google_apis/drive/test_util.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace google_apis {
namespace {
const char kValidJsonString[] = "{ \"test\": 123 }";
const char kInvalidJsonString[] = "$$$";
class FakeUrlFetchRequest : public UrlFetchRequestBase {
public:
FakeUrlFetchRequest(RequestSender* sender,
const EntryActionCallback& callback,
const GURL& url)
: UrlFetchRequestBase(sender),
callback_(callback),
url_(url) {
}
~FakeUrlFetchRequest() override {}
protected:
GURL GetURL() const override { return url_; }
void ProcessURLFetchResults(const net::URLFetcher* source) override {
callback_.Run(GetErrorCode());
}
void RunCallbackOnPrematureFailure(DriveApiErrorCode code) override {
callback_.Run(code);
}
EntryActionCallback callback_;
GURL url_;
};
class FakeMultipartUploadRequest : public MultipartUploadRequestBase {
public:
FakeMultipartUploadRequest(
base::SequencedTaskRunner* blocking_task_runner,
const std::string& metadata_json,
const std::string& content_type,
int64_t content_length,
const base::FilePath& local_file_path,
const FileResourceCallback& callback,
const google_apis::ProgressCallback& progress_callback,
const GURL& url,
std::string* upload_content_type,
std::string* upload_content_data)
: MultipartUploadRequestBase(blocking_task_runner,
metadata_json,
content_type,
content_length,
local_file_path,
callback,
progress_callback),
url_(url),
upload_content_type_(upload_content_type),
upload_content_data_(upload_content_data) {}
~FakeMultipartUploadRequest() override {}
net::URLFetcher::RequestType GetRequestType() const override {
return net::URLFetcher::POST;
}
bool GetContentData(std::string* content_type,
std::string* content_data) override {
const bool result =
MultipartUploadRequestBase::GetContentData(content_type, content_data);
*upload_content_type_ = *content_type;
*upload_content_data_ = *content_data;
return result;
}
protected:
GURL GetURL() const override { return url_; }
private:
const GURL url_;
std::string* const upload_content_type_;
std::string* const upload_content_data_;
};
} // namespace
class BaseRequestsTest : public testing::Test {
public:
BaseRequestsTest() : response_code_(net::HTTP_OK) {}
void SetUp() override {
request_context_getter_ = new net::TestURLRequestContextGetter(
message_loop_.task_runner());
sender_.reset(new RequestSender(new DummyAuthService,
request_context_getter_.get(),
message_loop_.task_runner(),
std::string() /* custom user agent */));
ASSERT_TRUE(test_server_.Start());
test_server_.RegisterRequestHandler(
base::Bind(&BaseRequestsTest::HandleRequest, base::Unretained(this)));
}
std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
const net::test_server::HttpRequest& request) {
std::unique_ptr<net::test_server::BasicHttpResponse> response(
new net::test_server::BasicHttpResponse);
response->set_code(response_code_);
response->set_content(response_body_);
response->set_content_type("application/json");
return std::move(response);
}
base::MessageLoopForIO message_loop_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
std::unique_ptr<RequestSender> sender_;
net::EmbeddedTestServer test_server_;
net::HttpStatusCode response_code_;
std::string response_body_;
};
typedef BaseRequestsTest MultipartUploadRequestBaseTest;
TEST_F(BaseRequestsTest, ParseValidJson) {
std::unique_ptr<base::Value> json(ParseJson(kValidJsonString));
base::DictionaryValue* root_dict = NULL;
ASSERT_TRUE(json);
ASSERT_TRUE(json->GetAsDictionary(&root_dict));
int int_value = 0;
ASSERT_TRUE(root_dict->GetInteger("test", &int_value));
EXPECT_EQ(123, int_value);
}
TEST_F(BaseRequestsTest, ParseInvalidJson) {
EXPECT_FALSE(ParseJson(kInvalidJsonString));
}
TEST_F(BaseRequestsTest, UrlFetchRequestBaseResponseCodeOverride) {
response_code_ = net::HTTP_FORBIDDEN;
response_body_ =
"{\"error\": {\n"
" \"errors\": [\n"
" {\n"
" \"domain\": \"usageLimits\",\n"
" \"reason\": \"rateLimitExceeded\",\n"
" \"message\": \"Rate Limit Exceeded\"\n"
" }\n"
" ],\n"
" \"code\": 403,\n"
" \"message\": \"Rate Limit Exceeded\"\n"
" }\n"
"}\n";
DriveApiErrorCode error = DRIVE_OTHER_ERROR;
base::RunLoop run_loop;
sender_->StartRequestWithAuthRetry(new FakeUrlFetchRequest(
sender_.get(),
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error)),
test_server_.base_url()));
run_loop.Run();
// HTTP_FORBIDDEN (403) is overridden by the error reason.
EXPECT_EQ(HTTP_SERVICE_UNAVAILABLE, error);
}
TEST_F(MultipartUploadRequestBaseTest, Basic) {
response_code_ = net::HTTP_OK;
response_body_ = "{\"kind\": \"drive#file\", \"id\": \"file_id\"}";
std::unique_ptr<google_apis::FileResource> file;
DriveApiErrorCode error = DRIVE_OTHER_ERROR;
base::RunLoop run_loop;
const base::FilePath source_path =
google_apis::test_util::GetTestFilePath("drive/text.txt");
std::string upload_content_type;
std::string upload_content_data;
FakeMultipartUploadRequest* const multipart_request =
new FakeMultipartUploadRequest(
sender_->blocking_task_runner(), "{json:\"test\"}", "text/plain", 10,
source_path,
test_util::CreateQuitCallback(
&run_loop, test_util::CreateCopyResultCallback(&error, &file)),
ProgressCallback(), test_server_.base_url(), &upload_content_type,
&upload_content_data);
multipart_request->SetBoundaryForTesting("TESTBOUNDARY");
std::unique_ptr<drive::SingleBatchableDelegateRequest> request(
new drive::SingleBatchableDelegateRequest(sender_.get(),
multipart_request));
sender_->StartRequestWithAuthRetry(request.release());
run_loop.Run();
EXPECT_EQ("multipart/related; boundary=TESTBOUNDARY", upload_content_type);
EXPECT_EQ(
"--TESTBOUNDARY\n"
"Content-Type: application/json\n"
"\n"
"{json:\"test\"}\n"
"--TESTBOUNDARY\n"
"Content-Type: text/plain\n"
"\n"
"This is a sample file. I like chocolate and chips.\n"
"\n"
"--TESTBOUNDARY--",
upload_content_data);
ASSERT_EQ(HTTP_SUCCESS, error);
EXPECT_EQ("file_id", file->file_id());
}
} // Namespace google_apis