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