privet_http_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright 2013 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 "chrome/browser/local_discovery/privet_http_impl.h"
8#include "net/base/host_port_pair.h"
9#include "net/base/net_errors.h"
10#include "net/url_request/test_url_fetcher_factory.h"
11#include "net/url_request/url_request_test_util.h"
12#include "testing/gmock/include/gmock/gmock.h"
13#include "testing/gtest/include/gtest/gtest.h"
14
15using testing::StrictMock;
16using testing::NiceMock;
17
18namespace local_discovery {
19
20namespace {
21
22const char kSampleInfoResponse[] = "{"
23    "       \"version\": \"1.0\","
24    "       \"name\": \"Common printer\","
25    "       \"description\": \"Printer connected through Chrome connector\","
26    "       \"url\": \"https://www.google.com/cloudprint\","
27    "       \"type\": ["
28    "               \"printer\""
29    "       ],"
30    "       \"id\": \"\","
31    "       \"device_state\": \"idle\","
32    "       \"connection_state\": \"online\","
33    "       \"manufacturer\": \"Google\","
34    "       \"model\": \"Google Chrome\","
35    "       \"serial_number\": \"1111-22222-33333-4444\","
36    "       \"firmware\": \"24.0.1312.52\","
37    "       \"uptime\": 600,"
38    "       \"setup_url\": \"http://support.google.com/\","
39    "       \"support_url\": \"http://support.google.com/cloudprint/?hl=en\","
40    "       \"update_url\": \"http://support.google.com/cloudprint/?hl=en\","
41    "       \"x-privet-token\": \"SampleTokenForTesting\","
42    "       \"api\": ["
43    "               \"/privet/accesstoken\","
44    "               \"/privet/capabilities\","
45    "               \"/privet/printer/submitdoc\","
46    "       ]"
47    "}";
48
49const char kSampleInfoResponseRegistered[] = "{"
50    "       \"version\": \"1.0\","
51    "       \"name\": \"Common printer\","
52    "       \"description\": \"Printer connected through Chrome connector\","
53    "       \"url\": \"https://www.google.com/cloudprint\","
54    "       \"type\": ["
55    "               \"printer\""
56    "       ],"
57    "       \"id\": \"MyDeviceID\","
58    "       \"device_state\": \"idle\","
59    "       \"connection_state\": \"online\","
60    "       \"manufacturer\": \"Google\","
61    "       \"model\": \"Google Chrome\","
62    "       \"serial_number\": \"1111-22222-33333-4444\","
63    "       \"firmware\": \"24.0.1312.52\","
64    "       \"uptime\": 600,"
65    "       \"setup_url\": \"http://support.google.com/\","
66    "       \"support_url\": \"http://support.google.com/cloudprint/?hl=en\","
67    "       \"update_url\": \"http://support.google.com/cloudprint/?hl=en\","
68    "       \"x-privet-token\": \"SampleTokenForTesting\","
69    "       \"api\": ["
70    "               \"/privet/accesstoken\","
71    "               \"/privet/capabilities\","
72    "               \"/privet/printer/submitdoc\","
73    "       ]"
74    "}";
75
76const char kSampleInfoResponseWithCreatejob[] = "{"
77    "       \"version\": \"1.0\","
78    "       \"name\": \"Common printer\","
79    "       \"description\": \"Printer connected through Chrome connector\","
80    "       \"url\": \"https://www.google.com/cloudprint\","
81    "       \"type\": ["
82    "               \"printer\""
83    "       ],"
84    "       \"id\": \"\","
85    "       \"device_state\": \"idle\","
86    "       \"connection_state\": \"online\","
87    "       \"manufacturer\": \"Google\","
88    "       \"model\": \"Google Chrome\","
89    "       \"serial_number\": \"1111-22222-33333-4444\","
90    "       \"firmware\": \"24.0.1312.52\","
91    "       \"uptime\": 600,"
92    "       \"setup_url\": \"http://support.google.com/\","
93    "       \"support_url\": \"http://support.google.com/cloudprint/?hl=en\","
94    "       \"update_url\": \"http://support.google.com/cloudprint/?hl=en\","
95    "       \"x-privet-token\": \"SampleTokenForTesting\","
96    "       \"api\": ["
97    "               \"/privet/accesstoken\","
98    "               \"/privet/capabilities\","
99    "               \"/privet/printer/createjob\","
100    "               \"/privet/printer/submitdoc\","
101    "       ]"
102    "}";
103
104const char kSampleRegisterStartResponse[] = "{"
105    "\"user\": \"example@google.com\","
106    "\"action\": \"start\""
107    "}";
108
109const char kSampleRegisterGetClaimTokenResponse[] = "{"
110    "       \"action\": \"getClaimToken\","
111    "       \"user\": \"example@google.com\","
112    "       \"token\": \"MySampleToken\","
113    "       \"claim_url\": \"https://domain.com/SoMeUrL\""
114    "}";
115
116const char kSampleRegisterCompleteResponse[] = "{"
117    "\"user\": \"example@google.com\","
118    "\"action\": \"complete\","
119    "\"device_id\": \"MyDeviceID\""
120    "}";
121
122const char kSampleXPrivetErrorResponse[] =
123    "{ \"error\": \"invalid_x_privet_token\" }";
124
125const char kSampleRegisterErrorTransient[] =
126    "{ \"error\": \"device_busy\", \"timeout\": 1}";
127
128const char kSampleRegisterErrorPermanent[] =
129    "{ \"error\": \"user_cancel\" }";
130
131const char kSampleInfoResponseBadJson[] = "{";
132
133const char kSampleRegisterCancelResponse[] = "{"
134    "\"user\": \"example@google.com\","
135    "\"action\": \"cancel\""
136    "}";
137
138const char kSampleLocalPrintResponse[] = "{"
139    "\"job_id\": \"123\","
140    "\"expires_in\": 500,"
141    "\"job_type\": \"application/pdf\","
142    "\"job_size\": 16,"
143    "\"job_name\": \"Sample job name\","
144    "}";
145
146const char kSampleCapabilitiesResponse[] = "{"
147    "\"version\" : \"1.0\","
148    "\"printer\" : {"
149    "  \"supported_content_type\" : ["
150    "   { \"content_type\" : \"application/pdf\" },"
151    "   { \"content_type\" : \"image/pwg-raster\" }"
152    "  ]"
153    "}"
154    "}";
155
156const char kSampleCapabilitiesResponsePWGOnly[] = "{"
157    "\"version\" : \"1.0\","
158    "\"printer\" : {"
159    "  \"supported_content_type\" : ["
160    "   { \"content_type\" : \"image/pwg-raster\" }"
161    "  ]"
162    "}"
163    "}";
164
165const char kSampleCapabilitiesResponseWithAnyMimetype[] = "{"
166    "\"version\" : \"1.0\","
167    "\"printer\" : {"
168    "  \"supported_content_type\" : ["
169    "   { \"content_type\" : \"*/*\" },"
170    "   { \"content_type\" : \"image/pwg-raster\" }"
171    "  ]"
172    "}"
173    "}";
174
175const char kSampleErrorResponsePrinterBusy[] = "{"
176    "\"error\": \"invalid_print_job\","
177    "\"timeout\": 1 "
178    "}";
179
180const char kSampleInvalidDocumentTypeResponse[] = "{"
181    "\"error\" : \"invalid_document_type\""
182    "}";
183
184const char kSampleCreatejobResponse[] = "{ \"job_id\": \"1234\" }";
185
186const char kSampleEmptyJSONResponse[] = "{}";
187
188class MockTestURLFetcherFactoryDelegate
189    : public net::TestURLFetcher::DelegateForTests {
190 public:
191  // Callback issued correspondingly to the call to the |Start()| method.
192  MOCK_METHOD1(OnRequestStart, void(int fetcher_id));
193
194  // Callback issued correspondingly to the call to |AppendChunkToUpload|.
195  // Uploaded chunks can be retrieved with the |upload_chunks()| getter.
196  MOCK_METHOD1(OnChunkUpload, void(int fetcher_id));
197
198  // Callback issued correspondingly to the destructor.
199  MOCK_METHOD1(OnRequestEnd, void(int fetcher_id));
200};
201
202class PrivetHTTPTest : public ::testing::Test {
203 public:
204  PrivetHTTPTest() {
205    request_context_= new net::TestURLRequestContextGetter(
206        base::MessageLoopProxy::current());
207    privet_client_.reset(new PrivetHTTPClientImpl(
208        "sampleDevice._privet._tcp.local",
209        net::HostPortPair("10.0.0.8", 6006),
210        request_context_.get()));
211    fetcher_factory_.SetDelegateForTests(&fetcher_delegate_);
212  }
213
214  virtual ~PrivetHTTPTest() {
215  }
216
217  bool SuccessfulResponseToURL(const GURL& url,
218                               const std::string& response) {
219    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
220    EXPECT_TRUE(fetcher);
221    EXPECT_EQ(url, fetcher->GetOriginalURL());
222
223    if (!fetcher || url != fetcher->GetOriginalURL())
224      return false;
225
226    fetcher->SetResponseString(response);
227    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
228                                              net::OK));
229    fetcher->set_response_code(200);
230    fetcher->delegate()->OnURLFetchComplete(fetcher);
231    return true;
232  }
233
234  bool SuccessfulResponseToURLAndData(const GURL& url,
235                                      const std::string& data,
236                                      const std::string& response) {
237    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
238    EXPECT_TRUE(fetcher);
239    EXPECT_EQ(url, fetcher->GetOriginalURL());
240
241    if (!fetcher) return false;
242
243    EXPECT_EQ(data, fetcher->upload_data());
244    if (data != fetcher->upload_data()) return false;
245
246    return SuccessfulResponseToURL(url, response);
247  }
248
249  bool SuccessfulResponseToURLAndFilePath(const GURL& url,
250                                          const base::FilePath& file_path,
251                                          const std::string& response) {
252    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
253    EXPECT_TRUE(fetcher);
254    EXPECT_EQ(url, fetcher->GetOriginalURL());
255
256    if (!fetcher) return false;
257
258    EXPECT_EQ(file_path, fetcher->upload_file_path());
259    if (file_path != fetcher->upload_file_path()) return false;
260
261    return SuccessfulResponseToURL(url, response);
262  }
263
264
265  void RunFor(base::TimeDelta time_period) {
266    base::CancelableCallback<void()> callback(base::Bind(
267        &PrivetHTTPTest::Stop, base::Unretained(this)));
268    base::MessageLoop::current()->PostDelayedTask(
269        FROM_HERE, callback.callback(), time_period);
270
271    base::MessageLoop::current()->Run();
272    callback.Cancel();
273  }
274
275  void Stop() {
276    base::MessageLoop::current()->Quit();
277  }
278
279 protected:
280  base::MessageLoop loop_;
281  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
282  net::TestURLFetcherFactory fetcher_factory_;
283  scoped_ptr<PrivetHTTPClient> privet_client_;
284  NiceMock<MockTestURLFetcherFactoryDelegate> fetcher_delegate_;
285};
286
287class MockJSONCallback{
288 public:
289  MockJSONCallback() {}
290  ~MockJSONCallback() {}
291
292  void OnPrivetJSONDone(const base::DictionaryValue* value) {
293    if (!value) {
294      value_.reset();
295    } else {
296      value_.reset(value->DeepCopy());
297    }
298
299    OnPrivetJSONDoneInternal();
300  }
301
302  MOCK_METHOD0(OnPrivetJSONDoneInternal, void());
303
304  const base::DictionaryValue* value() { return value_.get(); }
305  PrivetJSONOperation::ResultCallback callback() {
306    return base::Bind(&MockJSONCallback::OnPrivetJSONDone,
307                      base::Unretained(this));
308  }
309 protected:
310  scoped_ptr<base::DictionaryValue> value_;
311};
312
313class MockRegisterDelegate : public PrivetRegisterOperation::Delegate {
314 public:
315  MockRegisterDelegate() {
316  }
317  ~MockRegisterDelegate() {
318  }
319
320  virtual void OnPrivetRegisterClaimToken(
321      PrivetRegisterOperation* operation,
322      const std::string& token,
323      const GURL& url) OVERRIDE {
324    OnPrivetRegisterClaimTokenInternal(token, url);
325  }
326
327  MOCK_METHOD2(OnPrivetRegisterClaimTokenInternal, void(
328      const std::string& token,
329      const GURL& url));
330
331  virtual void OnPrivetRegisterError(
332      PrivetRegisterOperation* operation,
333      const std::string& action,
334      PrivetRegisterOperation::FailureReason reason,
335      int printer_http_code,
336      const base::DictionaryValue* json) OVERRIDE {
337    // TODO(noamsml): Save and test for JSON?
338    OnPrivetRegisterErrorInternal(action, reason, printer_http_code);
339  }
340
341  MOCK_METHOD3(OnPrivetRegisterErrorInternal,
342               void(const std::string& action,
343                    PrivetRegisterOperation::FailureReason reason,
344                    int printer_http_code));
345
346  virtual void OnPrivetRegisterDone(
347      PrivetRegisterOperation* operation,
348      const std::string& device_id) OVERRIDE {
349    OnPrivetRegisterDoneInternal(device_id);
350  }
351
352  MOCK_METHOD1(OnPrivetRegisterDoneInternal,
353               void(const std::string& device_id));
354};
355
356class MockLocalPrintDelegate : public PrivetLocalPrintOperation::Delegate {
357 public:
358  MockLocalPrintDelegate() {}
359  ~MockLocalPrintDelegate() {}
360
361  virtual void OnPrivetPrintingDone(
362      const PrivetLocalPrintOperation* print_operation) {
363    OnPrivetPrintingDoneInternal();
364  }
365
366  MOCK_METHOD0(OnPrivetPrintingDoneInternal, void());
367
368  virtual void OnPrivetPrintingError(
369      const PrivetLocalPrintOperation* print_operation, int http_code) {
370    OnPrivetPrintingErrorInternal(http_code);
371  }
372
373  MOCK_METHOD1(OnPrivetPrintingErrorInternal, void(int http_code));
374};
375
376// A note on PWG raster conversion: The PWG raster converter used simply
377// converts strings to file paths based on them by appending "test.pdf", since
378// it's easier to test that way. Instead of using a mock, we simply check if the
379// request is uploading a file that is based on this pattern.
380class FakePWGRasterConverter : public PWGRasterConverter {
381 public:
382  FakePWGRasterConverter() {
383  }
384
385  virtual ~FakePWGRasterConverter() {
386  }
387
388  virtual void Start(base::RefCountedMemory* data,
389                     const printing::PdfRenderSettings& conversion_settings,
390                     const ResultCallback& callback) OVERRIDE {
391    std::string data_str(data->front_as<char>(), data->size());
392    callback.Run(true, base::FilePath().AppendASCII(data_str + "test.pdf"));
393  }
394};
395
396TEST_F(PrivetHTTPTest, CreatePrivetStorageList) {
397  MockJSONCallback mock_callback;
398  scoped_ptr<PrivetJSONOperation> storage_list_operation =
399      privet_client_->CreateStorageListOperation(
400          "/path/to/nothing",
401          mock_callback.callback());
402  storage_list_operation->Start();
403
404  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
405                                      kSampleInfoResponse));
406
407  EXPECT_CALL(mock_callback, OnPrivetJSONDoneInternal());
408
409  EXPECT_TRUE(SuccessfulResponseToURL(
410      GURL("http://10.0.0.8:6006/privet/storage/list?path=/path/to/nothing"),
411      kSampleEmptyJSONResponse));
412}
413
414class PrivetInfoTest : public PrivetHTTPTest {
415 public:
416  PrivetInfoTest() {}
417
418  virtual ~PrivetInfoTest() {}
419
420  virtual void SetUp() OVERRIDE {
421    info_operation_ = privet_client_->CreateInfoOperation(
422        info_callback_.callback());
423  }
424
425 protected:
426  scoped_ptr<PrivetJSONOperation> info_operation_;
427  StrictMock<MockJSONCallback> info_callback_;
428};
429
430TEST_F(PrivetInfoTest, SuccessfulInfo) {
431  info_operation_->Start();
432
433  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
434  ASSERT_TRUE(fetcher != NULL);
435  EXPECT_EQ(GURL("http://10.0.0.8:6006/privet/info"),
436            fetcher->GetOriginalURL());
437
438  fetcher->SetResponseString(kSampleInfoResponse);
439  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
440                                            net::OK));
441  fetcher->set_response_code(200);
442
443  EXPECT_CALL(info_callback_, OnPrivetJSONDoneInternal());
444  fetcher->delegate()->OnURLFetchComplete(fetcher);
445
446  std::string name;
447
448  privet_client_->GetCachedInfo()->GetString("name", &name);
449  EXPECT_EQ("Common printer", name);
450};
451
452TEST_F(PrivetInfoTest, InfoSaveToken) {
453  info_operation_->Start();
454
455  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
456  ASSERT_TRUE(fetcher != NULL);
457  fetcher->SetResponseString(kSampleInfoResponse);
458  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
459                                            net::OK));
460  fetcher->set_response_code(200);
461
462  EXPECT_CALL(info_callback_, OnPrivetJSONDoneInternal());
463  fetcher->delegate()->OnURLFetchComplete(fetcher);
464
465  info_operation_ =
466      privet_client_->CreateInfoOperation(info_callback_.callback());
467  info_operation_->Start();
468
469  fetcher = fetcher_factory_.GetFetcherByID(0);
470  ASSERT_TRUE(fetcher != NULL);
471  net::HttpRequestHeaders headers;
472  fetcher->GetExtraRequestHeaders(&headers);
473  std::string header_token;
474  ASSERT_TRUE(headers.GetHeader("X-Privet-Token", &header_token));
475  EXPECT_EQ("SampleTokenForTesting", header_token);
476};
477
478TEST_F(PrivetInfoTest, InfoFailureHTTP) {
479  info_operation_->Start();
480
481  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
482  ASSERT_TRUE(fetcher != NULL);
483  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
484                                            net::OK));
485  fetcher->set_response_code(404);
486
487  EXPECT_CALL(info_callback_, OnPrivetJSONDoneInternal());
488  fetcher->delegate()->OnURLFetchComplete(fetcher);
489  EXPECT_EQ(NULL, privet_client_->GetCachedInfo());
490};
491
492class PrivetRegisterTest : public PrivetHTTPTest {
493 public:
494  PrivetRegisterTest() {
495  }
496  virtual ~PrivetRegisterTest() {
497  }
498
499  virtual void SetUp() OVERRIDE {
500    info_operation_ = privet_client_->CreateInfoOperation(
501        info_callback_.callback());
502    register_operation_ =
503        privet_client_->CreateRegisterOperation("example@google.com",
504                                                &register_delegate_);
505  }
506
507 protected:
508  bool SuccessfulResponseToURL(const GURL& url,
509                               const std::string& response) {
510    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
511    EXPECT_TRUE(fetcher);
512    EXPECT_EQ(url, fetcher->GetOriginalURL());
513    if (!fetcher || url != fetcher->GetOriginalURL())
514      return false;
515
516    fetcher->SetResponseString(response);
517    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
518                                              net::OK));
519    fetcher->set_response_code(200);
520    fetcher->delegate()->OnURLFetchComplete(fetcher);
521    return true;
522  }
523
524  scoped_ptr<PrivetJSONOperation> info_operation_;
525  NiceMock<MockJSONCallback> info_callback_;
526  scoped_ptr<PrivetRegisterOperation> register_operation_;
527  StrictMock<MockRegisterDelegate> register_delegate_;
528};
529
530TEST_F(PrivetRegisterTest, RegisterSuccessSimple) {
531  // Start with info request first to populate XSRF token.
532  info_operation_->Start();
533
534  EXPECT_TRUE(SuccessfulResponseToURL(
535      GURL("http://10.0.0.8:6006/privet/info"),
536      kSampleInfoResponse));
537
538  register_operation_->Start();
539
540  EXPECT_TRUE(SuccessfulResponseToURL(
541      GURL("http://10.0.0.8:6006/privet/register?"
542           "action=start&user=example%40google.com"),
543      kSampleRegisterStartResponse));
544
545  EXPECT_CALL(register_delegate_, OnPrivetRegisterClaimTokenInternal(
546      "MySampleToken",
547      GURL("https://domain.com/SoMeUrL")));
548
549  EXPECT_TRUE(SuccessfulResponseToURL(
550      GURL("http://10.0.0.8:6006/privet/register?"
551           "action=getClaimToken&user=example%40google.com"),
552      kSampleRegisterGetClaimTokenResponse));
553
554  register_operation_->CompleteRegistration();
555
556  EXPECT_TRUE(SuccessfulResponseToURL(
557      GURL("http://10.0.0.8:6006/privet/register?"
558           "action=complete&user=example%40google.com"),
559      kSampleRegisterCompleteResponse));
560
561  EXPECT_CALL(register_delegate_, OnPrivetRegisterDoneInternal(
562      "MyDeviceID"));
563
564  EXPECT_TRUE(SuccessfulResponseToURL(
565      GURL("http://10.0.0.8:6006/privet/info"),
566      kSampleInfoResponseRegistered));
567}
568
569TEST_F(PrivetRegisterTest, RegisterNoInfoCall) {
570  register_operation_->Start();
571
572  EXPECT_TRUE(SuccessfulResponseToURL(
573      GURL("http://10.0.0.8:6006/privet/info"),
574      kSampleInfoResponse));
575
576  EXPECT_TRUE(SuccessfulResponseToURL(
577      GURL("http://10.0.0.8:6006/privet/register?"
578           "action=start&user=example%40google.com"),
579      kSampleRegisterStartResponse));
580}
581
582TEST_F(PrivetRegisterTest, RegisterXSRFFailure) {
583  register_operation_->Start();
584
585  EXPECT_TRUE(SuccessfulResponseToURL(
586      GURL("http://10.0.0.8:6006/privet/info"),
587      kSampleInfoResponse));
588
589  EXPECT_TRUE(SuccessfulResponseToURL(
590      GURL("http://10.0.0.8:6006/privet/register?"
591           "action=start&user=example%40google.com"),
592      kSampleRegisterStartResponse));
593
594  EXPECT_TRUE(SuccessfulResponseToURL(
595      GURL("http://10.0.0.8:6006/privet/register?"
596           "action=getClaimToken&user=example%40google.com"),
597      kSampleXPrivetErrorResponse));
598
599  EXPECT_TRUE(SuccessfulResponseToURL(
600      GURL("http://10.0.0.8:6006/privet/info"),
601      kSampleInfoResponse));
602
603  EXPECT_CALL(register_delegate_, OnPrivetRegisterClaimTokenInternal(
604      "MySampleToken", GURL("https://domain.com/SoMeUrL")));
605
606  EXPECT_TRUE(SuccessfulResponseToURL(
607      GURL("http://10.0.0.8:6006/privet/register?"
608           "action=getClaimToken&user=example%40google.com"),
609      kSampleRegisterGetClaimTokenResponse));
610}
611
612TEST_F(PrivetRegisterTest, TransientFailure) {
613  register_operation_->Start();
614
615  EXPECT_TRUE(SuccessfulResponseToURL(
616      GURL("http://10.0.0.8:6006/privet/info"),
617      kSampleInfoResponse));
618
619  EXPECT_TRUE(SuccessfulResponseToURL(
620      GURL("http://10.0.0.8:6006/privet/register?"
621           "action=start&user=example%40google.com"),
622      kSampleRegisterErrorTransient));
623
624  EXPECT_CALL(fetcher_delegate_, OnRequestStart(0));
625
626  RunFor(base::TimeDelta::FromSeconds(2));
627
628  testing::Mock::VerifyAndClearExpectations(&fetcher_delegate_);
629
630  EXPECT_TRUE(SuccessfulResponseToURL(
631      GURL("http://10.0.0.8:6006/privet/register?"
632           "action=start&user=example%40google.com"),
633      kSampleRegisterStartResponse));
634}
635
636TEST_F(PrivetRegisterTest, PermanentFailure) {
637  register_operation_->Start();
638
639  EXPECT_TRUE(SuccessfulResponseToURL(
640      GURL("http://10.0.0.8:6006/privet/info"),
641      kSampleInfoResponse));
642
643  EXPECT_TRUE(SuccessfulResponseToURL(
644      GURL("http://10.0.0.8:6006/privet/register?"
645           "action=start&user=example%40google.com"),
646      kSampleRegisterStartResponse));
647
648  EXPECT_CALL(register_delegate_,
649              OnPrivetRegisterErrorInternal(
650                  "getClaimToken",
651                  PrivetRegisterOperation::FAILURE_JSON_ERROR,
652                  200));
653
654  EXPECT_TRUE(SuccessfulResponseToURL(
655      GURL("http://10.0.0.8:6006/privet/register?"
656           "action=getClaimToken&user=example%40google.com"),
657      kSampleRegisterErrorPermanent));
658}
659
660TEST_F(PrivetRegisterTest, InfoFailure) {
661  register_operation_->Start();
662
663  EXPECT_CALL(register_delegate_,
664              OnPrivetRegisterErrorInternal(
665                  "start",
666                  PrivetRegisterOperation::FAILURE_TOKEN,
667                  -1));
668
669  EXPECT_TRUE(SuccessfulResponseToURL(
670      GURL("http://10.0.0.8:6006/privet/info"),
671      kSampleInfoResponseBadJson));
672}
673
674TEST_F(PrivetRegisterTest, RegisterCancel) {
675  // Start with info request first to populate XSRF token.
676  info_operation_->Start();
677
678  EXPECT_TRUE(SuccessfulResponseToURL(
679      GURL("http://10.0.0.8:6006/privet/info"),
680      kSampleInfoResponse));
681
682  register_operation_->Start();
683
684  EXPECT_TRUE(SuccessfulResponseToURL(
685      GURL("http://10.0.0.8:6006/privet/register?"
686           "action=start&user=example%40google.com"),
687      kSampleRegisterStartResponse));
688
689  register_operation_->Cancel();
690
691  EXPECT_TRUE(SuccessfulResponseToURL(
692      GURL("http://10.0.0.8:6006/privet/register?"
693           "action=cancel&user=example%40google.com"),
694      kSampleRegisterCancelResponse));
695
696  // Must keep mocks alive for 3 seconds so the cancelation object can be
697  // deleted.
698  RunFor(base::TimeDelta::FromSeconds(3));
699}
700
701class PrivetCapabilitiesTest : public PrivetHTTPTest {
702 public:
703  PrivetCapabilitiesTest() {}
704
705  virtual ~PrivetCapabilitiesTest() {}
706
707  virtual void SetUp() OVERRIDE {
708    capabilities_operation_ = privet_client_->CreateCapabilitiesOperation(
709        capabilities_callback_.callback());
710  }
711
712 protected:
713  scoped_ptr<PrivetJSONOperation> capabilities_operation_;
714  StrictMock<MockJSONCallback> capabilities_callback_;
715};
716
717TEST_F(PrivetCapabilitiesTest, SuccessfulCapabilities) {
718  capabilities_operation_->Start();
719
720  EXPECT_TRUE(SuccessfulResponseToURL(
721      GURL("http://10.0.0.8:6006/privet/info"),
722      kSampleInfoResponse));
723
724  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
725
726  EXPECT_TRUE(SuccessfulResponseToURL(
727      GURL("http://10.0.0.8:6006/privet/capabilities"),
728      kSampleCapabilitiesResponse));
729
730  std::string version;
731  EXPECT_TRUE(capabilities_callback_.value()->GetString("version", &version));
732  EXPECT_EQ("1.0", version);
733};
734
735TEST_F(PrivetCapabilitiesTest, CacheToken) {
736  capabilities_operation_->Start();
737
738  EXPECT_TRUE(SuccessfulResponseToURL(
739      GURL("http://10.0.0.8:6006/privet/info"),
740      kSampleInfoResponse));
741
742  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
743
744  EXPECT_TRUE(SuccessfulResponseToURL(
745      GURL("http://10.0.0.8:6006/privet/capabilities"),
746      kSampleCapabilitiesResponse));
747
748  capabilities_operation_ = privet_client_->CreateCapabilitiesOperation(
749      capabilities_callback_.callback());
750
751  capabilities_operation_->Start();
752
753  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
754
755  EXPECT_TRUE(SuccessfulResponseToURL(
756      GURL("http://10.0.0.8:6006/privet/capabilities"),
757      kSampleCapabilitiesResponse));
758};
759
760TEST_F(PrivetCapabilitiesTest, BadToken) {
761  capabilities_operation_->Start();
762
763  EXPECT_TRUE(SuccessfulResponseToURL(
764      GURL("http://10.0.0.8:6006/privet/info"),
765      kSampleInfoResponse));
766
767  EXPECT_TRUE(SuccessfulResponseToURL(
768      GURL("http://10.0.0.8:6006/privet/capabilities"),
769      kSampleXPrivetErrorResponse));
770
771  EXPECT_TRUE(SuccessfulResponseToURL(
772      GURL("http://10.0.0.8:6006/privet/info"),
773      kSampleInfoResponse));
774
775  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
776
777  EXPECT_TRUE(SuccessfulResponseToURL(
778      GURL("http://10.0.0.8:6006/privet/capabilities"),
779      kSampleCapabilitiesResponse));
780};
781
782class PrivetLocalPrintTest : public PrivetHTTPTest {
783 public:
784  PrivetLocalPrintTest() {}
785
786  virtual ~PrivetLocalPrintTest() {}
787
788  virtual void SetUp() OVERRIDE {
789    local_print_operation_ = privet_client_->CreateLocalPrintOperation(
790        &local_print_delegate_);
791
792    local_print_operation_->SetPWGRasterConverterForTesting(
793        scoped_ptr<PWGRasterConverter>(new FakePWGRasterConverter));
794  }
795
796  scoped_refptr<base::RefCountedBytes> RefCountedBytesFromString(
797      std::string str) {
798    std::vector<unsigned char> str_vec;
799    str_vec.insert(str_vec.begin(), str.begin(), str.end());
800    return scoped_refptr<base::RefCountedBytes>(
801        base::RefCountedBytes::TakeVector(&str_vec));
802  }
803
804 protected:
805  scoped_ptr<PrivetLocalPrintOperation> local_print_operation_;
806  StrictMock<MockLocalPrintDelegate> local_print_delegate_;
807};
808
809TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrint) {
810  local_print_operation_->SetUsername("sample@gmail.com");
811  local_print_operation_->SetJobname("Sample job name");
812  local_print_operation_->SetData(RefCountedBytesFromString(
813      "Sample print data"));
814  local_print_operation_->Start();
815
816  EXPECT_TRUE(SuccessfulResponseToURL(
817      GURL("http://10.0.0.8:6006/privet/info"),
818      kSampleInfoResponse));
819
820  EXPECT_TRUE(SuccessfulResponseToURL(
821      GURL("http://10.0.0.8:6006/privet/capabilities"),
822      kSampleCapabilitiesResponse));
823
824  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
825
826  // TODO(noamsml): Is encoding spaces as pluses standard?
827  EXPECT_TRUE(SuccessfulResponseToURLAndData(
828      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
829           "client_name=Chrome&user_name=sample%40gmail.com&"
830           "job_name=Sample+job+name"),
831      "Sample print data",
832      kSampleLocalPrintResponse));
833};
834
835TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithAnyMimetype) {
836  local_print_operation_->SetUsername("sample@gmail.com");
837  local_print_operation_->SetJobname("Sample job name");
838  local_print_operation_->SetData(
839      RefCountedBytesFromString("Sample print data"));
840  local_print_operation_->Start();
841
842  EXPECT_TRUE(SuccessfulResponseToURL(
843      GURL("http://10.0.0.8:6006/privet/info"),
844      kSampleInfoResponse));
845
846  EXPECT_TRUE(SuccessfulResponseToURL(
847      GURL("http://10.0.0.8:6006/privet/capabilities"),
848      kSampleCapabilitiesResponseWithAnyMimetype));
849
850  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
851
852  // TODO(noamsml): Is encoding spaces as pluses standard?
853  EXPECT_TRUE(SuccessfulResponseToURLAndData(
854      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
855           "client_name=Chrome&user_name=sample%40gmail.com&"
856           "job_name=Sample+job+name"),
857      "Sample print data",
858      kSampleLocalPrintResponse));
859};
860
861TEST_F(PrivetLocalPrintTest, SuccessfulPWGLocalPrint) {
862  local_print_operation_->SetUsername("sample@gmail.com");
863  local_print_operation_->SetJobname("Sample job name");
864  local_print_operation_->SetData(
865      RefCountedBytesFromString("path/to/"));
866  local_print_operation_->Start();
867
868  EXPECT_TRUE(SuccessfulResponseToURL(
869      GURL("http://10.0.0.8:6006/privet/info"),
870      kSampleInfoResponse));
871
872  EXPECT_TRUE(SuccessfulResponseToURL(
873      GURL("http://10.0.0.8:6006/privet/capabilities"),
874      kSampleCapabilitiesResponsePWGOnly));
875
876  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
877
878  // TODO(noamsml): Is encoding spaces as pluses standard?
879  EXPECT_TRUE(SuccessfulResponseToURLAndFilePath(
880      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
881           "client_name=Chrome&user_name=sample%40gmail.com"
882           "&job_name=Sample+job+name"),
883      base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")),
884      kSampleLocalPrintResponse));
885};
886
887TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithCreatejob) {
888  local_print_operation_->SetUsername("sample@gmail.com");
889  local_print_operation_->SetJobname("Sample job name");
890  local_print_operation_->SetTicket("Sample print ticket");
891  local_print_operation_->SetData(
892      RefCountedBytesFromString("Sample print data"));
893  local_print_operation_->Start();
894
895  EXPECT_TRUE(SuccessfulResponseToURL(
896      GURL("http://10.0.0.8:6006/privet/info"),
897      kSampleInfoResponseWithCreatejob));
898
899  EXPECT_TRUE(SuccessfulResponseToURL(
900      GURL("http://10.0.0.8:6006/privet/capabilities"),
901      kSampleCapabilitiesResponse));
902
903  EXPECT_TRUE(SuccessfulResponseToURLAndData(
904      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
905      "Sample print ticket",
906      kSampleCreatejobResponse));
907
908  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
909
910  // TODO(noamsml): Is encoding spaces as pluses standard?
911  EXPECT_TRUE(SuccessfulResponseToURLAndData(
912      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
913           "client_name=Chrome&user_name=sample%40gmail.com&"
914           "job_name=Sample+job+name&job_id=1234"),
915      "Sample print data",
916      kSampleLocalPrintResponse));
917};
918
919TEST_F(PrivetLocalPrintTest, PDFPrintInvalidDocumentTypeRetry) {
920  local_print_operation_->SetUsername("sample@gmail.com");
921  local_print_operation_->SetJobname("Sample job name");
922  local_print_operation_->SetTicket("Sample print ticket");
923  local_print_operation_->SetData(
924      RefCountedBytesFromString("sample/path/"));
925  local_print_operation_->Start();
926
927  EXPECT_TRUE(SuccessfulResponseToURL(
928      GURL("http://10.0.0.8:6006/privet/info"),
929      kSampleInfoResponseWithCreatejob));
930
931  EXPECT_TRUE(SuccessfulResponseToURL(
932      GURL("http://10.0.0.8:6006/privet/capabilities"),
933      kSampleCapabilitiesResponse));
934
935  EXPECT_TRUE(SuccessfulResponseToURLAndData(
936      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
937      "Sample print ticket",
938      kSampleCreatejobResponse));
939
940  // TODO(noamsml): Is encoding spaces as pluses standard?
941  EXPECT_TRUE(SuccessfulResponseToURLAndData(
942      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
943           "client_name=Chrome&user_name=sample%40gmail.com&"
944           "job_name=Sample+job+name&job_id=1234"),
945      "sample/path/",
946      kSampleInvalidDocumentTypeResponse));
947
948  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
949
950  EXPECT_TRUE(SuccessfulResponseToURLAndFilePath(
951      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
952           "client_name=Chrome&user_name=sample%40gmail.com&"
953           "job_name=Sample+job+name&job_id=1234"),
954      base::FilePath(FILE_PATH_LITERAL("sample/path/test.pdf")),
955      kSampleLocalPrintResponse));
956};
957
958TEST_F(PrivetLocalPrintTest, LocalPrintRetryOnInvalidJobID) {
959  local_print_operation_->SetUsername("sample@gmail.com");
960  local_print_operation_->SetJobname("Sample job name");
961  local_print_operation_->SetTicket("Sample print ticket");
962  local_print_operation_->SetData(
963      RefCountedBytesFromString("Sample print data"));
964  local_print_operation_->Start();
965
966  EXPECT_TRUE(SuccessfulResponseToURL(
967      GURL("http://10.0.0.8:6006/privet/info"),
968      kSampleInfoResponseWithCreatejob));
969
970  EXPECT_TRUE(SuccessfulResponseToURL(
971      GURL("http://10.0.0.8:6006/privet/capabilities"),
972      kSampleCapabilitiesResponse));
973
974  EXPECT_TRUE(SuccessfulResponseToURLAndData(
975      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
976      "Sample print ticket",
977      kSampleCreatejobResponse));
978
979  EXPECT_TRUE(SuccessfulResponseToURLAndData(
980      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
981           "client_name=Chrome&user_name=sample%40gmail.com&"
982           "job_name=Sample+job+name&job_id=1234"),
983      "Sample print data",
984      kSampleErrorResponsePrinterBusy));
985
986  RunFor(base::TimeDelta::FromSeconds(3));
987
988  EXPECT_TRUE(SuccessfulResponseToURL(
989      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
990      kSampleCreatejobResponse));
991};
992
993
994}  // namespace
995
996}  // namespace local_discovery
997