1// Copyright (c) 2012 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 "base/bind.h"
6#include "base/message_loop/message_loop.h"
7#include "base/run_loop.h"
8#include "google_apis/drive/dummy_auth_service.h"
9#include "google_apis/drive/gdata_wapi_parser.h"
10#include "google_apis/drive/gdata_wapi_requests.h"
11#include "google_apis/drive/gdata_wapi_url_generator.h"
12#include "google_apis/drive/request_sender.h"
13#include "google_apis/drive/test_util.h"
14#include "net/base/escape.h"
15#include "net/test/embedded_test_server/embedded_test_server.h"
16#include "net/test/embedded_test_server/http_request.h"
17#include "net/test/embedded_test_server/http_response.h"
18#include "net/url_request/url_request_test_util.h"
19#include "testing/gtest/include/gtest/gtest.h"
20
21namespace google_apis {
22
23namespace {
24
25const char kTestUserAgent[] = "test-user-agent";
26
27class GDataWapiRequestsTest : public testing::Test {
28 public:
29  virtual void SetUp() OVERRIDE {
30    request_context_getter_ = new net::TestURLRequestContextGetter(
31        message_loop_.message_loop_proxy());
32
33    request_sender_.reset(new RequestSender(new DummyAuthService,
34                                            request_context_getter_.get(),
35                                            message_loop_.message_loop_proxy(),
36                                            kTestUserAgent));
37
38    ASSERT_TRUE(test_server_.InitializeAndWaitUntilReady());
39    test_server_.RegisterRequestHandler(
40        base::Bind(&GDataWapiRequestsTest::HandleResourceFeedRequest,
41                   base::Unretained(this)));
42
43    GURL test_base_url = test_util::GetBaseUrlForTesting(test_server_.port());
44    url_generator_.reset(new GDataWapiUrlGenerator(test_base_url));
45  }
46
47 protected:
48  // Handles a request for fetching a resource feed.
49  scoped_ptr<net::test_server::HttpResponse> HandleResourceFeedRequest(
50      const net::test_server::HttpRequest& request) {
51    http_request_ = request;
52
53    const GURL absolute_url = test_server_.GetURL(request.relative_url);
54    std::string remaining_path;
55
56    if (!test_util::RemovePrefix(absolute_url.path(),
57                                 "/feeds/default/private/full",
58                                 &remaining_path)) {
59      return scoped_ptr<net::test_server::HttpResponse>();
60    }
61
62    // Process a feed for a single resource ID.
63    const std::string resource_id = net::UnescapeURLComponent(
64        remaining_path.substr(1), net::UnescapeRule::URL_SPECIAL_CHARS);
65    if (resource_id == "file:2_file_resource_id") {
66      scoped_ptr<net::test_server::BasicHttpResponse> result(
67          test_util::CreateHttpResponseFromFile(
68              test_util::GetTestFilePath("gdata/file_entry.json")));
69      return result.PassAs<net::test_server::HttpResponse>();
70    } else if (resource_id == "invalid_resource_id") {
71      // Check if this is an authorization request for an app.
72      // This emulates to return invalid formatted result from the server.
73      if (request.method == net::test_server::METHOD_PUT &&
74          request.content.find("<docs:authorizedApp>") != std::string::npos) {
75        scoped_ptr<net::test_server::BasicHttpResponse> result(
76            test_util::CreateHttpResponseFromFile(
77                test_util::GetTestFilePath("drive/testfile.txt")));
78        return result.PassAs<net::test_server::HttpResponse>();
79      }
80    }
81
82    return scoped_ptr<net::test_server::HttpResponse>();
83  }
84
85  base::MessageLoopForIO message_loop_;  // Test server needs IO thread.
86  net::test_server::EmbeddedTestServer test_server_;
87  scoped_ptr<RequestSender> request_sender_;
88  scoped_ptr<GDataWapiUrlGenerator> url_generator_;
89  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
90
91  // The incoming HTTP request is saved so tests can verify the request
92  // parameters like HTTP method (ex. some requests should use DELETE
93  // instead of GET).
94  net::test_server::HttpRequest http_request_;
95};
96
97}  // namespace
98
99TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_ValidResourceId) {
100  GDataErrorCode result_code = GDATA_OTHER_ERROR;
101  scoped_ptr<ResourceEntry> result_data;
102
103  {
104    base::RunLoop run_loop;
105    GetResourceEntryRequest* request = new GetResourceEntryRequest(
106        request_sender_.get(),
107        *url_generator_,
108        "file:2_file_resource_id",  // resource ID
109        GURL(),  // embed origin
110        test_util::CreateQuitCallback(
111            &run_loop,
112            test_util::CreateCopyResultCallback(&result_code, &result_data)));
113    request_sender_->StartRequestWithRetry(request);
114    run_loop.Run();
115  }
116
117  EXPECT_EQ(HTTP_SUCCESS, result_code);
118  EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
119  EXPECT_EQ("/feeds/default/private/full/file%3A2_file_resource_id"
120            "?v=3&alt=json&showroot=true",
121            http_request_.relative_url);
122  EXPECT_TRUE(result_data);
123  EXPECT_EQ("File 1.mp3", result_data->filename());
124  EXPECT_EQ("3b4382ebefec6e743578c76bbd0575ce", result_data->file_md5());
125}
126
127TEST_F(GDataWapiRequestsTest, GetResourceEntryRequest_InvalidResourceId) {
128  GDataErrorCode result_code = GDATA_OTHER_ERROR;
129  scoped_ptr<ResourceEntry> result_data;
130
131  {
132    base::RunLoop run_loop;
133    GetResourceEntryRequest* request = new GetResourceEntryRequest(
134        request_sender_.get(),
135        *url_generator_,
136        "<invalid>",  // resource ID
137        GURL(),  // embed origin
138        test_util::CreateQuitCallback(
139            &run_loop,
140            test_util::CreateCopyResultCallback(&result_code, &result_data)));
141    request_sender_->StartRequestWithRetry(request);
142    run_loop.Run();
143  }
144
145  EXPECT_EQ(HTTP_NOT_FOUND, result_code);
146  EXPECT_EQ(net::test_server::METHOD_GET, http_request_.method);
147  EXPECT_EQ("/feeds/default/private/full/%3Cinvalid%3E?v=3&alt=json"
148            "&showroot=true",
149            http_request_.relative_url);
150  ASSERT_FALSE(result_data);
151}
152
153}  // namespace google_apis
154