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