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