privet_http_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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    PrivetURLFetcher::ResetTokenMapForTests();
206
207    request_context_= new net::TestURLRequestContextGetter(
208        base::MessageLoopProxy::current());
209    privet_client_.reset(new PrivetHTTPClientImpl(
210        "sampleDevice._privet._tcp.local",
211        net::HostPortPair("10.0.0.8", 6006),
212        request_context_.get()));
213    fetcher_factory_.SetDelegateForTests(&fetcher_delegate_);
214  }
215
216  virtual ~PrivetHTTPTest() {
217  }
218
219  bool SuccessfulResponseToURL(const GURL& url,
220                               const std::string& response) {
221    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
222    EXPECT_TRUE(fetcher);
223    EXPECT_EQ(url, fetcher->GetOriginalURL());
224
225    if (!fetcher || url != fetcher->GetOriginalURL())
226      return false;
227
228    fetcher->SetResponseString(response);
229    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
230                                              net::OK));
231    fetcher->set_response_code(200);
232    fetcher->delegate()->OnURLFetchComplete(fetcher);
233    return true;
234  }
235
236  bool SuccessfulResponseToURLAndData(const GURL& url,
237                                      const std::string& data,
238                                      const std::string& response) {
239    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
240    EXPECT_TRUE(fetcher);
241    EXPECT_EQ(url, fetcher->GetOriginalURL());
242
243    if (!fetcher) return false;
244
245    EXPECT_EQ(data, fetcher->upload_data());
246    if (data != fetcher->upload_data()) return false;
247
248    return SuccessfulResponseToURL(url, response);
249  }
250
251  bool SuccessfulResponseToURLAndFilePath(const GURL& url,
252                                          const base::FilePath& file_path,
253                                          const std::string& response) {
254    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
255    EXPECT_TRUE(fetcher);
256    EXPECT_EQ(url, fetcher->GetOriginalURL());
257
258    if (!fetcher) return false;
259
260    EXPECT_EQ(file_path, fetcher->upload_file_path());
261    if (file_path != fetcher->upload_file_path()) return false;
262
263    return SuccessfulResponseToURL(url, response);
264  }
265
266
267  void RunFor(base::TimeDelta time_period) {
268    base::CancelableCallback<void()> callback(base::Bind(
269        &PrivetHTTPTest::Stop, base::Unretained(this)));
270    base::MessageLoop::current()->PostDelayedTask(
271        FROM_HERE, callback.callback(), time_period);
272
273    base::MessageLoop::current()->Run();
274    callback.Cancel();
275  }
276
277  void Stop() {
278    base::MessageLoop::current()->Quit();
279  }
280
281 protected:
282  base::MessageLoop loop_;
283  scoped_refptr<net::TestURLRequestContextGetter> request_context_;
284  net::TestURLFetcherFactory fetcher_factory_;
285  scoped_ptr<PrivetHTTPClient> privet_client_;
286  NiceMock<MockTestURLFetcherFactoryDelegate> fetcher_delegate_;
287};
288
289class MockJSONCallback{
290 public:
291  MockJSONCallback() {}
292  ~MockJSONCallback() {}
293
294  void OnPrivetJSONDone(const base::DictionaryValue* value) {
295    if (!value) {
296      value_.reset();
297    } else {
298      value_.reset(value->DeepCopy());
299    }
300
301    OnPrivetJSONDoneInternal();
302  }
303
304  MOCK_METHOD0(OnPrivetJSONDoneInternal, void());
305
306  const base::DictionaryValue* value() { return value_.get(); }
307  PrivetJSONOperation::ResultCallback callback() {
308    return base::Bind(&MockJSONCallback::OnPrivetJSONDone,
309                      base::Unretained(this));
310  }
311 protected:
312  scoped_ptr<base::DictionaryValue> value_;
313};
314
315class MockRegisterDelegate : public PrivetRegisterOperation::Delegate {
316 public:
317  MockRegisterDelegate() {
318  }
319  ~MockRegisterDelegate() {
320  }
321
322  virtual void OnPrivetRegisterClaimToken(
323      PrivetRegisterOperation* operation,
324      const std::string& token,
325      const GURL& url) OVERRIDE {
326    OnPrivetRegisterClaimTokenInternal(token, url);
327  }
328
329  MOCK_METHOD2(OnPrivetRegisterClaimTokenInternal, void(
330      const std::string& token,
331      const GURL& url));
332
333  virtual void OnPrivetRegisterError(
334      PrivetRegisterOperation* operation,
335      const std::string& action,
336      PrivetRegisterOperation::FailureReason reason,
337      int printer_http_code,
338      const base::DictionaryValue* json) OVERRIDE {
339    // TODO(noamsml): Save and test for JSON?
340    OnPrivetRegisterErrorInternal(action, reason, printer_http_code);
341  }
342
343  MOCK_METHOD3(OnPrivetRegisterErrorInternal,
344               void(const std::string& action,
345                    PrivetRegisterOperation::FailureReason reason,
346                    int printer_http_code));
347
348  virtual void OnPrivetRegisterDone(
349      PrivetRegisterOperation* operation,
350      const std::string& device_id) OVERRIDE {
351    OnPrivetRegisterDoneInternal(device_id);
352  }
353
354  MOCK_METHOD1(OnPrivetRegisterDoneInternal,
355               void(const std::string& device_id));
356};
357
358class MockLocalPrintDelegate : public PrivetLocalPrintOperation::Delegate {
359 public:
360  MockLocalPrintDelegate() {}
361  ~MockLocalPrintDelegate() {}
362
363  virtual void OnPrivetPrintingDone(
364      const PrivetLocalPrintOperation* print_operation) {
365    OnPrivetPrintingDoneInternal();
366  }
367
368  MOCK_METHOD0(OnPrivetPrintingDoneInternal, void());
369
370  virtual void OnPrivetPrintingError(
371      const PrivetLocalPrintOperation* print_operation, int http_code) {
372    OnPrivetPrintingErrorInternal(http_code);
373  }
374
375  MOCK_METHOD1(OnPrivetPrintingErrorInternal, void(int http_code));
376};
377
378// A note on PWG raster conversion: The PWG raster converter used simply
379// converts strings to file paths based on them by appending "test.pdf", since
380// it's easier to test that way. Instead of using a mock, we simply check if the
381// request is uploading a file that is based on this pattern.
382class FakePWGRasterConverter : public PWGRasterConverter {
383 public:
384  FakePWGRasterConverter() {
385  }
386
387  virtual ~FakePWGRasterConverter() {
388  }
389
390  virtual void Start(base::RefCountedMemory* data,
391                     const printing::PdfRenderSettings& conversion_settings,
392                     const ResultCallback& callback) OVERRIDE {
393    std::string data_str(data->front_as<char>(), data->size());
394    callback.Run(true, base::FilePath().AppendASCII(data_str + "test.pdf"));
395  }
396};
397
398TEST_F(PrivetHTTPTest, CreatePrivetStorageList) {
399  MockJSONCallback mock_callback;
400  scoped_ptr<PrivetJSONOperation> storage_list_operation =
401      privet_client_->CreateStorageListOperation(
402          "/path/to/nothing",
403          mock_callback.callback());
404  storage_list_operation->Start();
405
406  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
407                                      kSampleInfoResponse));
408
409  EXPECT_CALL(mock_callback, OnPrivetJSONDoneInternal());
410
411  EXPECT_TRUE(SuccessfulResponseToURL(
412      GURL("http://10.0.0.8:6006/privet/storage/list?path=/path/to/nothing"),
413      kSampleEmptyJSONResponse));
414}
415
416class PrivetInfoTest : public PrivetHTTPTest {
417 public:
418  PrivetInfoTest() {}
419
420  virtual ~PrivetInfoTest() {}
421
422  virtual void SetUp() OVERRIDE {
423    info_operation_ = privet_client_->CreateInfoOperation(
424        info_callback_.callback());
425  }
426
427 protected:
428  scoped_ptr<PrivetJSONOperation> info_operation_;
429  StrictMock<MockJSONCallback> info_callback_;
430};
431
432TEST_F(PrivetInfoTest, SuccessfulInfo) {
433  info_operation_->Start();
434
435  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
436  ASSERT_TRUE(fetcher != NULL);
437  EXPECT_EQ(GURL("http://10.0.0.8:6006/privet/info"),
438            fetcher->GetOriginalURL());
439
440  fetcher->SetResponseString(kSampleInfoResponse);
441  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
442                                            net::OK));
443  fetcher->set_response_code(200);
444
445  EXPECT_CALL(info_callback_, OnPrivetJSONDoneInternal());
446  fetcher->delegate()->OnURLFetchComplete(fetcher);
447};
448
449TEST_F(PrivetInfoTest, InfoFailureHTTP) {
450  info_operation_->Start();
451
452  net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
453  ASSERT_TRUE(fetcher != NULL);
454  fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
455                                            net::OK));
456  fetcher->set_response_code(404);
457
458  EXPECT_CALL(info_callback_, OnPrivetJSONDoneInternal());
459  fetcher->delegate()->OnURLFetchComplete(fetcher);
460};
461
462class PrivetRegisterTest : public PrivetHTTPTest {
463 public:
464  PrivetRegisterTest() {
465  }
466  virtual ~PrivetRegisterTest() {
467  }
468
469  virtual void SetUp() OVERRIDE {
470    info_operation_ = privet_client_->CreateInfoOperation(
471        info_callback_.callback());
472    register_operation_ =
473        privet_client_->CreateRegisterOperation("example@google.com",
474                                                &register_delegate_);
475  }
476
477 protected:
478  bool SuccessfulResponseToURL(const GURL& url,
479                               const std::string& response) {
480    net::TestURLFetcher* fetcher = fetcher_factory_.GetFetcherByID(0);
481    EXPECT_TRUE(fetcher);
482    EXPECT_EQ(url, fetcher->GetOriginalURL());
483    if (!fetcher || url != fetcher->GetOriginalURL())
484      return false;
485
486    fetcher->SetResponseString(response);
487    fetcher->set_status(net::URLRequestStatus(net::URLRequestStatus::SUCCESS,
488                                              net::OK));
489    fetcher->set_response_code(200);
490    fetcher->delegate()->OnURLFetchComplete(fetcher);
491    return true;
492  }
493
494  scoped_ptr<PrivetJSONOperation> info_operation_;
495  NiceMock<MockJSONCallback> info_callback_;
496  scoped_ptr<PrivetRegisterOperation> register_operation_;
497  StrictMock<MockRegisterDelegate> register_delegate_;
498};
499
500TEST_F(PrivetRegisterTest, RegisterSuccessSimple) {
501  register_operation_->Start();
502
503  EXPECT_TRUE(SuccessfulResponseToURL(
504      GURL("http://10.0.0.8:6006/privet/info"),
505      kSampleInfoResponse));
506
507  EXPECT_TRUE(SuccessfulResponseToURL(
508      GURL("http://10.0.0.8:6006/privet/register?"
509           "action=start&user=example%40google.com"),
510      kSampleRegisterStartResponse));
511
512  EXPECT_CALL(register_delegate_, OnPrivetRegisterClaimTokenInternal(
513      "MySampleToken",
514      GURL("https://domain.com/SoMeUrL")));
515
516  EXPECT_TRUE(SuccessfulResponseToURL(
517      GURL("http://10.0.0.8:6006/privet/register?"
518           "action=getClaimToken&user=example%40google.com"),
519      kSampleRegisterGetClaimTokenResponse));
520
521  register_operation_->CompleteRegistration();
522
523  EXPECT_TRUE(SuccessfulResponseToURL(
524      GURL("http://10.0.0.8:6006/privet/register?"
525           "action=complete&user=example%40google.com"),
526      kSampleRegisterCompleteResponse));
527
528  EXPECT_CALL(register_delegate_, OnPrivetRegisterDoneInternal(
529      "MyDeviceID"));
530
531  EXPECT_TRUE(SuccessfulResponseToURL(
532      GURL("http://10.0.0.8:6006/privet/info"),
533      kSampleInfoResponseRegistered));
534}
535
536TEST_F(PrivetRegisterTest, RegisterXSRFFailure) {
537  register_operation_->Start();
538
539  EXPECT_TRUE(SuccessfulResponseToURL(
540      GURL("http://10.0.0.8:6006/privet/info"),
541      kSampleInfoResponse));
542
543  EXPECT_TRUE(SuccessfulResponseToURL(
544      GURL("http://10.0.0.8:6006/privet/register?"
545           "action=start&user=example%40google.com"),
546      kSampleRegisterStartResponse));
547
548  EXPECT_TRUE(SuccessfulResponseToURL(
549      GURL("http://10.0.0.8:6006/privet/register?"
550           "action=getClaimToken&user=example%40google.com"),
551      kSampleXPrivetErrorResponse));
552
553  EXPECT_TRUE(SuccessfulResponseToURL(
554      GURL("http://10.0.0.8:6006/privet/info"),
555      kSampleInfoResponse));
556
557  EXPECT_CALL(register_delegate_, OnPrivetRegisterClaimTokenInternal(
558      "MySampleToken", GURL("https://domain.com/SoMeUrL")));
559
560  EXPECT_TRUE(SuccessfulResponseToURL(
561      GURL("http://10.0.0.8:6006/privet/register?"
562           "action=getClaimToken&user=example%40google.com"),
563      kSampleRegisterGetClaimTokenResponse));
564}
565
566TEST_F(PrivetRegisterTest, TransientFailure) {
567  register_operation_->Start();
568
569  EXPECT_TRUE(SuccessfulResponseToURL(
570      GURL("http://10.0.0.8:6006/privet/info"),
571      kSampleInfoResponse));
572
573  EXPECT_TRUE(SuccessfulResponseToURL(
574      GURL("http://10.0.0.8:6006/privet/register?"
575           "action=start&user=example%40google.com"),
576      kSampleRegisterErrorTransient));
577
578  EXPECT_CALL(fetcher_delegate_, OnRequestStart(0));
579
580  RunFor(base::TimeDelta::FromSeconds(2));
581
582  testing::Mock::VerifyAndClearExpectations(&fetcher_delegate_);
583
584  EXPECT_TRUE(SuccessfulResponseToURL(
585      GURL("http://10.0.0.8:6006/privet/register?"
586           "action=start&user=example%40google.com"),
587      kSampleRegisterStartResponse));
588}
589
590TEST_F(PrivetRegisterTest, PermanentFailure) {
591  register_operation_->Start();
592
593  EXPECT_TRUE(SuccessfulResponseToURL(
594      GURL("http://10.0.0.8:6006/privet/info"),
595      kSampleInfoResponse));
596
597  EXPECT_TRUE(SuccessfulResponseToURL(
598      GURL("http://10.0.0.8:6006/privet/register?"
599           "action=start&user=example%40google.com"),
600      kSampleRegisterStartResponse));
601
602  EXPECT_CALL(register_delegate_,
603              OnPrivetRegisterErrorInternal(
604                  "getClaimToken",
605                  PrivetRegisterOperation::FAILURE_JSON_ERROR,
606                  200));
607
608  EXPECT_TRUE(SuccessfulResponseToURL(
609      GURL("http://10.0.0.8:6006/privet/register?"
610           "action=getClaimToken&user=example%40google.com"),
611      kSampleRegisterErrorPermanent));
612}
613
614TEST_F(PrivetRegisterTest, InfoFailure) {
615  register_operation_->Start();
616
617  EXPECT_CALL(register_delegate_,
618              OnPrivetRegisterErrorInternal(
619                  "start",
620                  PrivetRegisterOperation::FAILURE_TOKEN,
621                  -1));
622
623  EXPECT_TRUE(SuccessfulResponseToURL(
624      GURL("http://10.0.0.8:6006/privet/info"),
625      kSampleInfoResponseBadJson));
626}
627
628TEST_F(PrivetRegisterTest, RegisterCancel) {
629  register_operation_->Start();
630
631  EXPECT_TRUE(SuccessfulResponseToURL(
632      GURL("http://10.0.0.8:6006/privet/info"),
633      kSampleInfoResponse));
634
635  EXPECT_TRUE(SuccessfulResponseToURL(
636      GURL("http://10.0.0.8:6006/privet/register?"
637           "action=start&user=example%40google.com"),
638      kSampleRegisterStartResponse));
639
640  register_operation_->Cancel();
641
642  EXPECT_TRUE(SuccessfulResponseToURL(
643      GURL("http://10.0.0.8:6006/privet/register?"
644           "action=cancel&user=example%40google.com"),
645      kSampleRegisterCancelResponse));
646
647  // Must keep mocks alive for 3 seconds so the cancelation object can be
648  // deleted.
649  RunFor(base::TimeDelta::FromSeconds(3));
650}
651
652class PrivetCapabilitiesTest : public PrivetHTTPTest {
653 public:
654  PrivetCapabilitiesTest() {}
655
656  virtual ~PrivetCapabilitiesTest() {}
657
658  virtual void SetUp() OVERRIDE {
659    capabilities_operation_ = privet_client_->CreateCapabilitiesOperation(
660        capabilities_callback_.callback());
661  }
662
663 protected:
664  scoped_ptr<PrivetJSONOperation> capabilities_operation_;
665  StrictMock<MockJSONCallback> capabilities_callback_;
666};
667
668TEST_F(PrivetCapabilitiesTest, SuccessfulCapabilities) {
669  capabilities_operation_->Start();
670
671  EXPECT_TRUE(SuccessfulResponseToURL(
672      GURL("http://10.0.0.8:6006/privet/info"),
673      kSampleInfoResponse));
674
675  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
676
677  EXPECT_TRUE(SuccessfulResponseToURL(
678      GURL("http://10.0.0.8:6006/privet/capabilities"),
679      kSampleCapabilitiesResponse));
680
681  std::string version;
682  EXPECT_TRUE(capabilities_callback_.value()->GetString("version", &version));
683  EXPECT_EQ("1.0", version);
684};
685
686TEST_F(PrivetCapabilitiesTest, CacheToken) {
687  capabilities_operation_->Start();
688
689  EXPECT_TRUE(SuccessfulResponseToURL(
690      GURL("http://10.0.0.8:6006/privet/info"),
691      kSampleInfoResponse));
692
693  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
694
695  EXPECT_TRUE(SuccessfulResponseToURL(
696      GURL("http://10.0.0.8:6006/privet/capabilities"),
697      kSampleCapabilitiesResponse));
698
699  capabilities_operation_ = privet_client_->CreateCapabilitiesOperation(
700      capabilities_callback_.callback());
701
702  capabilities_operation_->Start();
703
704  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
705
706  EXPECT_TRUE(SuccessfulResponseToURL(
707      GURL("http://10.0.0.8:6006/privet/capabilities"),
708      kSampleCapabilitiesResponse));
709};
710
711TEST_F(PrivetCapabilitiesTest, BadToken) {
712  capabilities_operation_->Start();
713
714  EXPECT_TRUE(SuccessfulResponseToURL(
715      GURL("http://10.0.0.8:6006/privet/info"),
716      kSampleInfoResponse));
717
718  EXPECT_TRUE(SuccessfulResponseToURL(
719      GURL("http://10.0.0.8:6006/privet/capabilities"),
720      kSampleXPrivetErrorResponse));
721
722  EXPECT_TRUE(SuccessfulResponseToURL(
723      GURL("http://10.0.0.8:6006/privet/info"),
724      kSampleInfoResponse));
725
726  EXPECT_CALL(capabilities_callback_, OnPrivetJSONDoneInternal());
727
728  EXPECT_TRUE(SuccessfulResponseToURL(
729      GURL("http://10.0.0.8:6006/privet/capabilities"),
730      kSampleCapabilitiesResponse));
731};
732
733class PrivetLocalPrintTest : public PrivetHTTPTest {
734 public:
735  PrivetLocalPrintTest() {}
736
737  virtual ~PrivetLocalPrintTest() {}
738
739  virtual void SetUp() OVERRIDE {
740    PrivetURLFetcher::ResetTokenMapForTests();
741
742    local_print_operation_ = privet_client_->CreateLocalPrintOperation(
743        &local_print_delegate_);
744
745    local_print_operation_->SetPWGRasterConverterForTesting(
746        scoped_ptr<PWGRasterConverter>(new FakePWGRasterConverter));
747  }
748
749  scoped_refptr<base::RefCountedBytes> RefCountedBytesFromString(
750      std::string str) {
751    std::vector<unsigned char> str_vec;
752    str_vec.insert(str_vec.begin(), str.begin(), str.end());
753    return scoped_refptr<base::RefCountedBytes>(
754        base::RefCountedBytes::TakeVector(&str_vec));
755  }
756
757 protected:
758  scoped_ptr<PrivetLocalPrintOperation> local_print_operation_;
759  StrictMock<MockLocalPrintDelegate> local_print_delegate_;
760};
761
762TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrint) {
763  local_print_operation_->SetUsername("sample@gmail.com");
764  local_print_operation_->SetJobname("Sample job name");
765  local_print_operation_->SetData(RefCountedBytesFromString(
766      "Sample print data"));
767  local_print_operation_->Start();
768
769  EXPECT_TRUE(SuccessfulResponseToURL(
770      GURL("http://10.0.0.8:6006/privet/info"),
771      kSampleInfoResponse));
772
773  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
774                                      kSampleInfoResponse));
775
776  EXPECT_TRUE(
777      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
778                              kSampleCapabilitiesResponse));
779
780  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
781
782  // TODO(noamsml): Is encoding spaces as pluses standard?
783  EXPECT_TRUE(SuccessfulResponseToURLAndData(
784      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
785           "client_name=Chrome&user_name=sample%40gmail.com&"
786           "job_name=Sample+job+name"),
787      "Sample print data",
788      kSampleLocalPrintResponse));
789};
790
791TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithAnyMimetype) {
792  local_print_operation_->SetUsername("sample@gmail.com");
793  local_print_operation_->SetJobname("Sample job name");
794  local_print_operation_->SetData(
795      RefCountedBytesFromString("Sample print data"));
796  local_print_operation_->Start();
797
798  EXPECT_TRUE(SuccessfulResponseToURL(
799      GURL("http://10.0.0.8:6006/privet/info"),
800      kSampleInfoResponse));
801
802  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
803                                      kSampleInfoResponse));
804
805  EXPECT_TRUE(
806      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
807                              kSampleCapabilitiesResponseWithAnyMimetype));
808
809  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
810
811  // TODO(noamsml): Is encoding spaces as pluses standard?
812  EXPECT_TRUE(SuccessfulResponseToURLAndData(
813      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
814           "client_name=Chrome&user_name=sample%40gmail.com&"
815           "job_name=Sample+job+name"),
816      "Sample print data",
817      kSampleLocalPrintResponse));
818};
819
820TEST_F(PrivetLocalPrintTest, SuccessfulPWGLocalPrint) {
821  local_print_operation_->SetUsername("sample@gmail.com");
822  local_print_operation_->SetJobname("Sample job name");
823  local_print_operation_->SetData(
824      RefCountedBytesFromString("path/to/"));
825  local_print_operation_->Start();
826
827  EXPECT_TRUE(SuccessfulResponseToURL(
828      GURL("http://10.0.0.8:6006/privet/info"),
829      kSampleInfoResponse));
830
831  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
832                                      kSampleInfoResponse));
833
834  EXPECT_TRUE(
835      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
836                              kSampleCapabilitiesResponsePWGOnly));
837
838  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
839
840  // TODO(noamsml): Is encoding spaces as pluses standard?
841  EXPECT_TRUE(SuccessfulResponseToURLAndFilePath(
842      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
843           "client_name=Chrome&user_name=sample%40gmail.com"
844           "&job_name=Sample+job+name"),
845      base::FilePath(FILE_PATH_LITERAL("path/to/test.pdf")),
846      kSampleLocalPrintResponse));
847};
848
849TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithCreatejob) {
850  local_print_operation_->SetUsername("sample@gmail.com");
851  local_print_operation_->SetJobname("Sample job name");
852  local_print_operation_->SetTicket("Sample print ticket");
853  local_print_operation_->SetData(
854      RefCountedBytesFromString("Sample print data"));
855  local_print_operation_->Start();
856
857  EXPECT_TRUE(SuccessfulResponseToURL(
858      GURL("http://10.0.0.8:6006/privet/info"),
859      kSampleInfoResponseWithCreatejob));
860
861  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
862                                      kSampleInfoResponse));
863
864  EXPECT_TRUE(
865      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
866                              kSampleCapabilitiesResponse));
867
868  EXPECT_TRUE(SuccessfulResponseToURLAndData(
869      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
870      "Sample print ticket",
871      kSampleCreatejobResponse));
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&job_id=1234"),
880      "Sample print data",
881      kSampleLocalPrintResponse));
882};
883
884TEST_F(PrivetLocalPrintTest, SuccessfulLocalPrintWithOverlongName) {
885  local_print_operation_->SetUsername("sample@gmail.com");
886  local_print_operation_->SetJobname(
887      "123456789:123456789:123456789:123456789:123456789:123456789:123456789:");
888  local_print_operation_->SetTicket("Sample print ticket");
889  local_print_operation_->SetData(
890      RefCountedBytesFromString("Sample print data"));
891  local_print_operation_->Start();
892
893  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
894                                      kSampleInfoResponseWithCreatejob));
895
896  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
897                                      kSampleInfoResponse));
898
899  EXPECT_TRUE(
900      SuccessfulResponseToURL(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(
913          "http://10.0.0.8:6006/privet/printer/submitdoc?"
914          "client_name=Chrome&user_name=sample%40gmail.com&"
915          "job_name=123456789%3A123456789%3A123456789%3A1...123456789"
916          "%3A123456789%3A123456789%3A&job_id=1234"),
917      "Sample print data",
918      kSampleLocalPrintResponse));
919};
920
921TEST_F(PrivetLocalPrintTest, PDFPrintInvalidDocumentTypeRetry) {
922  local_print_operation_->SetUsername("sample@gmail.com");
923  local_print_operation_->SetJobname("Sample job name");
924  local_print_operation_->SetTicket("Sample print ticket");
925  local_print_operation_->SetData(
926      RefCountedBytesFromString("sample/path/"));
927  local_print_operation_->Start();
928
929  EXPECT_TRUE(SuccessfulResponseToURL(
930      GURL("http://10.0.0.8:6006/privet/info"),
931      kSampleInfoResponseWithCreatejob));
932
933  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
934                                      kSampleInfoResponse));
935
936  EXPECT_TRUE(
937      SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/capabilities"),
938                              kSampleCapabilitiesResponse));
939
940  EXPECT_TRUE(SuccessfulResponseToURLAndData(
941      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
942      "Sample print ticket",
943      kSampleCreatejobResponse));
944
945  // TODO(noamsml): Is encoding spaces as pluses standard?
946  EXPECT_TRUE(SuccessfulResponseToURLAndData(
947      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
948           "client_name=Chrome&user_name=sample%40gmail.com&"
949           "job_name=Sample+job+name&job_id=1234"),
950      "sample/path/",
951      kSampleInvalidDocumentTypeResponse));
952
953  EXPECT_CALL(local_print_delegate_, OnPrivetPrintingDoneInternal());
954
955  EXPECT_TRUE(SuccessfulResponseToURLAndFilePath(
956      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
957           "client_name=Chrome&user_name=sample%40gmail.com&"
958           "job_name=Sample+job+name&job_id=1234"),
959      base::FilePath(FILE_PATH_LITERAL("sample/path/test.pdf")),
960      kSampleLocalPrintResponse));
961};
962
963TEST_F(PrivetLocalPrintTest, LocalPrintRetryOnInvalidJobID) {
964  local_print_operation_->SetUsername("sample@gmail.com");
965  local_print_operation_->SetJobname("Sample job name");
966  local_print_operation_->SetTicket("Sample print ticket");
967  local_print_operation_->SetData(
968      RefCountedBytesFromString("Sample print data"));
969  local_print_operation_->Start();
970
971  EXPECT_TRUE(SuccessfulResponseToURL(
972      GURL("http://10.0.0.8:6006/privet/info"),
973      kSampleInfoResponseWithCreatejob));
974
975  EXPECT_TRUE(SuccessfulResponseToURL(GURL("http://10.0.0.8:6006/privet/info"),
976                                      kSampleInfoResponse));
977
978  EXPECT_TRUE(SuccessfulResponseToURL(
979      GURL("http://10.0.0.8:6006/privet/capabilities"),
980      kSampleCapabilitiesResponse));
981
982  EXPECT_TRUE(SuccessfulResponseToURLAndData(
983      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
984      "Sample print ticket",
985      kSampleCreatejobResponse));
986
987  EXPECT_TRUE(SuccessfulResponseToURLAndData(
988      GURL("http://10.0.0.8:6006/privet/printer/submitdoc?"
989           "client_name=Chrome&user_name=sample%40gmail.com&"
990           "job_name=Sample+job+name&job_id=1234"),
991      "Sample print data",
992      kSampleErrorResponsePrinterBusy));
993
994  RunFor(base::TimeDelta::FromSeconds(3));
995
996  EXPECT_TRUE(SuccessfulResponseToURL(
997      GURL("http://10.0.0.8:6006/privet/printer/createjob"),
998      kSampleCreatejobResponse));
999};
1000
1001
1002}  // namespace
1003
1004}  // namespace local_discovery
1005