• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 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/files/file_path.h"
6 #include "base/md5.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/common/cloud_print/cloud_print_constants.h"
13 #include "chrome/service/cloud_print/cloud_print_service_helpers.h"
14 #include "chrome/service/cloud_print/cloud_print_token_store.h"
15 #include "chrome/service/cloud_print/print_system.h"
16 #include "chrome/service/cloud_print/printer_job_handler.h"
17 #include "net/http/http_response_headers.h"
18 #include "net/http/http_status_code.h"
19 #include "net/url_request/test_url_fetcher_factory.h"
20 #include "net/url_request/url_request_status.h"
21 #include "net/url_request/url_request_test_util.h"
22 #include "printing/backend/print_backend.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 
26 using ::testing::AtLeast;
27 using ::testing::DoAll;
28 using ::testing::Exactly;
29 using ::testing::Invoke;
30 using ::testing::InvokeWithoutArgs;
31 using ::testing::NiceMock;
32 using ::testing::Return;
33 using ::testing::SaveArg;
34 using ::testing::Sequence;
35 using ::testing::SetArgPointee;
36 using ::testing::StrictMock;
37 using ::testing::_;
38 
39 namespace cloud_print {
40 
41 namespace {
42 
43 using base::StringPrintf;
44 
45 const char kExampleCloudPrintServerURL[] = "https://www.google.com/cloudprint/";
46 
47 const char kExamplePrintTicket[] = "{\"MediaType\":\"plain\","
48     "\"Resolution\":\"300x300dpi\",\"PageRegion\":\"Letter\","
49     "\"InputSlot\":\"auto\",\"PageSize\":\"Letter\",\"EconoMode\":\"off\"}";
50 
51 
52 // The fillowing constants will all be constructed with StringPrintf. The
53 // following types of parameters are possible:
54 // job number(int): ID # of job from given job list. All job IDs follow the
55 // format __example_job_idN for some N.
56 // fetch reason(string): Fetch reason used by the code. The job list URL
57 // requested by PrinterJobHandler has an extra parameter that signifies when
58 // the request was triggered.
59 // status string(string): Status of print job, one of IN_PROGRESS, DONE or ERROR
60 // job object list(string/JSON formatted): a comma-separated list of job objects
61 
62 // StringPrintf parameters: job number, job number, job number, job number
63 const char kExampleJobObject[] = "{"
64 "   \"tags\": ["
65 "    \"^own\""
66 "   ],"
67 "   \"printerName\": \"Example Printer\","
68 "   \"status\": \"QUEUED\","
69 "   \"ownerId\": \"sampleuser@gmail.com\","
70 "   \"ticketUrl\": \"https://www.google.com/cloudprint/ticket?exampleURI%d\","
71 "   \"printerid\": \"__example_printer_id\","
72 "   \"printerType\": \"GOOGLE\","
73 "   \"contentType\": \"text/html\","
74 "   \"fileUrl\": \"https://www.google.com/cloudprint/download?exampleURI%d\","
75 "   \"id\": \"__example_job_id%d\","
76 "   \"message\": \"\","
77 "   \"title\": \"Example Job %d\","
78 "   \"errorCode\": \"\","
79 "   \"numberOfPages\": 3"
80 "  }";
81 
82 // StringPrintf parameters: job object list
83 const char kExampleJobListResponse[] = "{"
84 " \"success\": true,"
85 " \"jobs\": ["
86 " %s"
87 " ],"
88 " \"xsrf_token\": \"AIp06DjUd3AV6BO0aujB9NvM2a9ZbogxOQ:1360021066932\","
89 " \"request\": {"
90 "  \"time\": \"0\","
91 "  \"users\": ["
92 "   \"sampleuser@gmail.com\""
93 "  ],"
94 "  \"params\": {"
95 "   \"printerid\": ["
96 "    \"__example_printer_id\""
97 "   ]"
98 "  },"
99 "  \"user\": \"sampleuser@gmail.com\""
100 " }"
101 "}";
102 
103 
104 // StringPrintf parameters: job number
105 const char kExampleJobID[] = "__example_job_id%d";
106 
107 // StringPrintf parameters: job number
108 const char kExamplePrintTicketURI[] =
109     "https://www.google.com/cloudprint/ticket?exampleURI%d";
110 
111 // StringPrintf parameters: job number
112 const char kExamplePrintDownloadURI[] =
113     "https://www.google.com/cloudprint/download?exampleURI%d";
114 
115 // StringPrintf parameters: job number
116 const char kExampleUpdateDoneURI[] =
117     "https://www.google.com/cloudprint/control?jobid=__example_job_id%d"
118     "&status=DONE&code=0&message=&numpages=0&pagesprinted=0";
119 
120 // StringPrintf parameters: job number
121 const char kExampleUpdateErrorURI[] =
122     "https://www.google.com/cloudprint/control?jobid=__example_job_id%d"
123     "&status=ERROR";
124 
125 // StringPrintf parameters: fetch reason
126 const char kExamplePrinterJobListURI[] =
127     "https://www.google.com/cloudprint/fetch"
128     "?printerid=__example_printer_id&deb=%s";
129 
130 // StringPrintf parameters: status string, job number, status string (repeat)
131 const char kExampleControlResponse[] = "{"
132 " \"success\": true,"
133 " \"message\": \"Print job updated successfully.\","
134 " \"xsrf_token\": \"AIp06DjKgbfGalbqzj23V1bU6i-vtR2B4w:1360023068789\","
135 " \"request\": {"
136 "  \"time\": \"0\","
137 "  \"users\": ["
138 "   \"sampleuser@gmail.com\""
139 "  ],"
140 "  \"params\": {"
141 "   \"xsrf\": ["
142 "    \"AIp06DgeGIETs42Cj28QWmxGPWVDiaXwVQ:1360023041852\""
143 "   ],"
144 "   \"status\": ["
145 "    \"%s\""
146 "   ],"
147 "   \"jobid\": ["
148 "    \"__example_job_id%d\""
149 "   ]"
150 "  },"
151 "  \"user\": \"sampleuser@gmail.com\""
152 " },"
153 " \"job\": {"
154 "  \"tags\": ["
155 "   \"^own\""
156 "  ],"
157 "  \"printerName\": \"Example Printer\","
158 "  \"status\": \"%s\","
159 "  \"ownerId\": \"sampleuser@gmail.com\","
160 "  \"ticketUrl\": \"https://www.google.com/cloudprint/ticket?exampleURI1\","
161 "  \"printerid\": \"__example_printer_id\","
162 "  \"contentType\": \"text/html\","
163 "  \"fileUrl\": \"https://www.google.com/cloudprint/download?exampleURI1\","
164 "  \"id\": \"__example_job_id1\","
165 "  \"message\": \"\","
166 "  \"title\": \"Example Job\","
167 "  \"errorCode\": \"\","
168 "  \"numberOfPages\": 3"
169 " }"
170 "}";
171 
172 const char kExamplePrinterID[] = "__example_printer_id";
173 
174 const char kExamplePrinterCapabilities[] = "";
175 
176 const char kExampleCapsMimeType[] = "";
177 
178 // These can stay empty
179 const char kExampleDefaults[] = "";
180 
181 const char kExampleDefaultMimeType[] = "";
182 
183 // Since we're not connecting to the server, this can be any non-empty string.
184 const char kExampleCloudPrintOAuthToken[] = "__SAMPLE_TOKEN";
185 
186 
187 // Not actually printing, no need for real PDF.
188 const char kExamplePrintData[] = "__EXAMPLE_PRINT_DATA";
189 
190 const char kExampleJobDownloadResponseHeaders[] =
191     "Content-Type: Application/PDF\n";
192 
193 const char kExampleTicketDownloadResponseHeaders[] =
194     "Content-Type: application/json\n";
195 
196 const char kExamplePrinterName[] = "Example Printer";
197 
198 const char kExamplePrinterDescription[] = "Example Description";
199 
200 // These are functions used to construct the various sample strings.
JobListResponse(int num_jobs)201 std::string JobListResponse(int num_jobs) {
202   std::string job_objects;
203   for (int i = 0; i < num_jobs; i++) {
204     job_objects = job_objects + StringPrintf(kExampleJobObject, i+1, i+1, i+1,
205                                              i+1);
206     if (i != num_jobs-1) job_objects = job_objects + ",";
207   }
208   return StringPrintf(kExampleJobListResponse, job_objects.c_str());
209 }
210 
JobListURI(const char * reason)211 GURL JobListURI(const char* reason) {
212   return GURL(StringPrintf(kExamplePrinterJobListURI, reason));
213 }
214 
DoneURI(int job_num)215 GURL DoneURI(int job_num) {
216   return GURL(StringPrintf(kExampleUpdateDoneURI, job_num));
217 }
218 
ErrorURI(int job_num)219 GURL ErrorURI(int job_num) {
220   return GURL(StringPrintf(kExampleUpdateErrorURI, job_num));
221 }
222 
TicketURI(int job_num)223 GURL TicketURI(int job_num) {
224   return GURL(StringPrintf(kExamplePrintTicketURI, job_num));
225 }
226 
DownloadURI(int job_num)227 GURL DownloadURI(int job_num) {
228   return GURL(StringPrintf(kExamplePrintDownloadURI, job_num));
229 }
230 
InProgressURI(int job_num)231 GURL InProgressURI(int job_num) {
232   return GetUrlForJobStatusUpdate(GURL(kExampleCloudPrintServerURL),
233                                   StringPrintf(kExampleJobID, job_num),
234                                   PRINT_JOB_STATUS_IN_PROGRESS,
235                                   0);
236 }
237 
StatusResponse(int job_num,const char * status_string)238 std::string StatusResponse(int job_num, const char* status_string) {
239   return StringPrintf(kExampleControlResponse,
240                       status_string,
241                       job_num,
242                       status_string);
243 }
244 
245 }  // namespace
246 
247 class CloudPrintURLFetcherNoServiceProcess
248     : public CloudPrintURLFetcher {
249  public:
CloudPrintURLFetcherNoServiceProcess()250   CloudPrintURLFetcherNoServiceProcess() :
251       context_getter_(new net::TestURLRequestContextGetter(
252           base::MessageLoopProxy::current())) {}
253  protected:
GetRequestContextGetter()254   virtual net::URLRequestContextGetter* GetRequestContextGetter() OVERRIDE {
255     return context_getter_.get();
256   }
257 
~CloudPrintURLFetcherNoServiceProcess()258   virtual ~CloudPrintURLFetcherNoServiceProcess() {}
259  private:
260   scoped_refptr<net::URLRequestContextGetter> context_getter_;
261 };
262 
263 
264 class CloudPrintURLFetcherNoServiceProcessFactory
265     : public CloudPrintURLFetcherFactory {
266  public:
CreateCloudPrintURLFetcher()267   virtual CloudPrintURLFetcher* CreateCloudPrintURLFetcher() OVERRIDE {
268     return new CloudPrintURLFetcherNoServiceProcess;
269   }
270 
~CloudPrintURLFetcherNoServiceProcessFactory()271   virtual ~CloudPrintURLFetcherNoServiceProcessFactory() {}
272 };
273 
274 
275 // This class handles the callback from FakeURLFetcher
276 // It is a separate class because callback methods must be
277 // on RefCounted classes
278 
279 class TestURLFetcherCallback {
280  public:
CreateURLFetcher(const GURL & url,net::URLFetcherDelegate * d,const std::string & response_data,net::HttpStatusCode response_code,net::URLRequestStatus::Status status)281   scoped_ptr<net::FakeURLFetcher> CreateURLFetcher(
282       const GURL& url,
283       net::URLFetcherDelegate* d,
284       const std::string& response_data,
285       net::HttpStatusCode response_code,
286       net::URLRequestStatus::Status status) {
287     scoped_ptr<net::FakeURLFetcher> fetcher(
288         new net::FakeURLFetcher(url, d, response_data, response_code, status));
289     OnRequestCreate(url, fetcher.get());
290     return fetcher.Pass();
291   }
292   MOCK_METHOD2(OnRequestCreate,
293                void(const GURL&, net::FakeURLFetcher*));
294 };
295 
296 
297 class MockPrinterJobHandlerDelegate
298     : public PrinterJobHandler::Delegate {
299  public:
300   MOCK_METHOD0(OnAuthError, void());
301   MOCK_METHOD1(OnPrinterDeleted, void(const std::string& str));
302 
~MockPrinterJobHandlerDelegate()303   virtual ~MockPrinterJobHandlerDelegate() {}
304 };
305 
306 
307 class MockPrintServerWatcher
308     : public PrintSystem::PrintServerWatcher {
309  public:
310   MOCK_METHOD1(StartWatching,
311                bool(PrintSystem::PrintServerWatcher::Delegate* d));
312   MOCK_METHOD0(StopWatching, bool());
313 
314   MockPrintServerWatcher();
delegate() const315   PrintSystem::PrintServerWatcher::Delegate* delegate() const {
316     return delegate_;
317   }
318 
319   friend class scoped_refptr<NiceMock<MockPrintServerWatcher> >;
320   friend class scoped_refptr<StrictMock<MockPrintServerWatcher> >;
321   friend class scoped_refptr<MockPrintServerWatcher>;
322 
323  protected:
~MockPrintServerWatcher()324   virtual ~MockPrintServerWatcher() {}
325 
326  private:
327   PrintSystem::PrintServerWatcher::Delegate* delegate_;
328 };
329 
330 class MockPrinterWatcher : public PrintSystem::PrinterWatcher {
331  public:
332   MOCK_METHOD1(StartWatching, bool(PrintSystem::PrinterWatcher::Delegate* d));
333   MOCK_METHOD0(StopWatching, bool());
334   MOCK_METHOD1(GetCurrentPrinterInfo,
335                bool(printing::PrinterBasicInfo* printer_info));
336 
337   MockPrinterWatcher();
delegate() const338   PrintSystem::PrinterWatcher::Delegate* delegate() const { return delegate_; }
339 
340   friend class scoped_refptr<NiceMock<MockPrinterWatcher> >;
341   friend class scoped_refptr<StrictMock<MockPrinterWatcher> >;
342   friend class scoped_refptr<MockPrinterWatcher>;
343 
344  protected:
~MockPrinterWatcher()345   virtual ~MockPrinterWatcher() {}
346 
347  private:
348   PrintSystem::PrinterWatcher::Delegate* delegate_;
349 };
350 
351 
352 class MockJobSpooler : public PrintSystem::JobSpooler {
353  public:
354   MOCK_METHOD8(Spool, bool(
355       const std::string& print_ticket,
356       const std::string& print_ticket_mime_type,
357       const base::FilePath& print_data_file_path,
358       const std::string& print_data_mime_type,
359       const std::string& printer_name,
360       const std::string& job_title,
361       const std::vector<std::string>& tags,
362       PrintSystem::JobSpooler::Delegate* delegate));
363 
364   MockJobSpooler();
delegate() const365   PrintSystem::JobSpooler::Delegate* delegate() const  { return delegate_; }
366 
367   friend class scoped_refptr<NiceMock<MockJobSpooler> >;
368   friend class scoped_refptr<StrictMock<MockJobSpooler> >;
369   friend class scoped_refptr<MockJobSpooler>;
370 
371  protected:
~MockJobSpooler()372   virtual ~MockJobSpooler() {}
373 
374  private:
375   PrintSystem::JobSpooler::Delegate* delegate_;
376 };
377 
378 
379 
380 class MockPrintSystem : public PrintSystem {
381  public:
382   MockPrintSystem();
succeed()383   PrintSystem::PrintSystemResult succeed() {
384     return PrintSystem::PrintSystemResult(true, "success");
385   }
386 
fail()387   PrintSystem::PrintSystemResult fail() {
388     return PrintSystem::PrintSystemResult(false, "failure");
389   }
390 
JobSpooler()391   MockJobSpooler& JobSpooler() { return *job_spooler_.get(); }
392 
PrinterWatcher()393   MockPrinterWatcher& PrinterWatcher() { return *printer_watcher_.get(); }
394 
PrintServerWatcher()395   MockPrintServerWatcher& PrintServerWatcher() {
396     return *print_server_watcher_.get();
397   }
398 
399   MOCK_METHOD0(Init, PrintSystem::PrintSystemResult());
400   MOCK_METHOD1(EnumeratePrinters, PrintSystem::PrintSystemResult(
401       printing::PrinterList* printer_list));
402 
403   MOCK_METHOD2(
404       GetPrinterCapsAndDefaults,
405       void(const std::string& printer_name,
406            const PrintSystem::PrinterCapsAndDefaultsCallback& callback));
407 
408   MOCK_METHOD1(IsValidPrinter, bool(const std::string& printer_name));
409 
410   MOCK_METHOD3(ValidatePrintTicket,
411                bool(const std::string& printer_name,
412                     const std::string& print_ticket_data,
413                     const std::string& print_ticket_mime_type));
414 
415   MOCK_METHOD3(GetJobDetails, bool(const std::string& printer_name,
416                                     PlatformJobId job_id,
417                                     PrintJobDetails* job_details));
418 
419   MOCK_METHOD0(CreatePrintServerWatcher, PrintSystem::PrintServerWatcher*());
420   MOCK_METHOD1(CreatePrinterWatcher,
421                PrintSystem::PrinterWatcher*(const std::string& printer_name));
422   MOCK_METHOD0(CreateJobSpooler, PrintSystem::JobSpooler*());
423 
424   MOCK_METHOD0(UseCddAndCjt, bool());
425   MOCK_METHOD0(GetSupportedMimeTypes, std::string());
426 
427   friend class scoped_refptr<NiceMock<MockPrintSystem> >;
428   friend class scoped_refptr<StrictMock<MockPrintSystem> >;
429   friend class scoped_refptr<MockPrintSystem>;
430 
431  protected:
~MockPrintSystem()432   virtual ~MockPrintSystem() {}
433 
434  private:
435   scoped_refptr<MockJobSpooler> job_spooler_;
436   scoped_refptr<MockPrinterWatcher> printer_watcher_;
437   scoped_refptr<MockPrintServerWatcher> print_server_watcher_;
438 };
439 
440 
441 class PrinterJobHandlerTest : public ::testing::Test {
442  public:
443   PrinterJobHandlerTest();
444   virtual void SetUp() OVERRIDE;
445   virtual void TearDown() OVERRIDE;
446   void IdleOut();
447   bool GetPrinterInfo(printing::PrinterBasicInfo* info);
448   void SendCapsAndDefaults(
449       const std::string& printer_name,
450       const PrintSystem::PrinterCapsAndDefaultsCallback& callback);
451   void AddMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher);
452   void AddTicketMimeHeader(const GURL& url, net::FakeURLFetcher* fetcher);
453   bool PostSpoolSuccess();
454   void SetUpJobSuccessTest(int job_num);
455   void BeginTest(int timeout_seconds);
456   void MakeJobFetchReturnNoJobs();
457 
458   static void MessageLoopQuitNowHelper(base::MessageLoop* message_loop);
459   static void MessageLoopQuitSoonHelper(base::MessageLoop* message_loop);
460 
461   base::MessageLoopForIO loop_;
462   TestURLFetcherCallback url_callback_;
463   MockPrinterJobHandlerDelegate jobhandler_delegate_;
464   CloudPrintTokenStore token_store_;
465   CloudPrintURLFetcherNoServiceProcessFactory cloud_print_factory_;
466   scoped_refptr<PrinterJobHandler> job_handler_;
467   scoped_refptr<NiceMock<MockPrintSystem> > print_system_;
468   net::FakeURLFetcherFactory factory_;
469   printing::PrinterBasicInfo basic_info_;
470   printing::PrinterCapsAndDefaults caps_and_defaults_;
471   PrinterJobHandler::PrinterInfoFromCloud info_from_cloud_;
472 };
473 
474 
SetUp()475 void PrinterJobHandlerTest::SetUp() {
476   basic_info_.printer_name = kExamplePrinterName;
477   basic_info_.printer_description = kExamplePrinterDescription;
478   basic_info_.is_default = 0;
479 
480   info_from_cloud_.printer_id = kExamplePrinterID;
481   info_from_cloud_.tags_hash = GetHashOfPrinterInfo(basic_info_);
482 
483   info_from_cloud_.caps_hash = base::MD5String(kExamplePrinterCapabilities);
484   info_from_cloud_.current_xmpp_timeout = 300;
485   info_from_cloud_.pending_xmpp_timeout = 0;
486 
487   caps_and_defaults_.printer_capabilities = kExamplePrinterCapabilities;
488   caps_and_defaults_.caps_mime_type = kExampleCapsMimeType;
489   caps_and_defaults_.printer_defaults = kExampleDefaults;
490   caps_and_defaults_.defaults_mime_type = kExampleDefaultMimeType;
491 
492   print_system_ = new NiceMock<MockPrintSystem>();
493 
494   token_store_.SetToken(kExampleCloudPrintOAuthToken);
495 
496   ON_CALL(print_system_->PrinterWatcher(), GetCurrentPrinterInfo(_))
497       .WillByDefault(Invoke(this, &PrinterJobHandlerTest::GetPrinterInfo));
498 
499   ON_CALL(*print_system_.get(), GetPrinterCapsAndDefaults(_, _))
500       .WillByDefault(Invoke(this, &PrinterJobHandlerTest::SendCapsAndDefaults));
501 
502   CloudPrintURLFetcher::set_factory(&cloud_print_factory_);
503 }
504 
MakeJobFetchReturnNoJobs()505 void PrinterJobHandlerTest::MakeJobFetchReturnNoJobs() {
506   factory_.SetFakeResponse(JobListURI(kJobFetchReasonStartup),
507                            JobListResponse(0), net::HTTP_OK,
508                            net::URLRequestStatus::SUCCESS);
509   factory_.SetFakeResponse(JobListURI(kJobFetchReasonFailure),
510                            JobListResponse(0), net::HTTP_OK,
511                            net::URLRequestStatus::SUCCESS);
512   factory_.SetFakeResponse(JobListURI(kJobFetchReasonRetry),
513                            JobListResponse(0), net::HTTP_OK,
514                            net::URLRequestStatus::SUCCESS);
515 }
516 
MessageLoopQuitNowHelper(base::MessageLoop * message_loop)517 void PrinterJobHandlerTest::MessageLoopQuitNowHelper(
518     base::MessageLoop* message_loop) {
519   message_loop->QuitWhenIdle();
520 }
521 
MessageLoopQuitSoonHelper(base::MessageLoop * message_loop)522 void PrinterJobHandlerTest::MessageLoopQuitSoonHelper(
523     base::MessageLoop* message_loop) {
524   message_loop->message_loop_proxy()->PostTask(
525       FROM_HERE, base::Bind(&MessageLoopQuitNowHelper, message_loop));
526 }
527 
PrinterJobHandlerTest()528 PrinterJobHandlerTest::PrinterJobHandlerTest()
529     : factory_(NULL, base::Bind(&TestURLFetcherCallback::CreateURLFetcher,
530                                 base::Unretained(&url_callback_))) {
531 }
532 
PostSpoolSuccess()533 bool PrinterJobHandlerTest::PostSpoolSuccess() {
534   base::MessageLoop::current()->PostTask(
535       FROM_HERE,
536       base::Bind(&PrinterJobHandler::OnJobSpoolSucceeded, job_handler_, 0));
537 
538   // Everything that would be posted on the printer thread queue
539   // has been posted, we can tell the main message loop to quit when idle
540   // and not worry about it idling while the print thread does work
541   base::MessageLoop::current()->PostTask(
542       FROM_HERE, base::Bind(&MessageLoopQuitSoonHelper, &loop_));
543   return true;
544 }
545 
AddMimeHeader(const GURL & url,net::FakeURLFetcher * fetcher)546 void PrinterJobHandlerTest::AddMimeHeader(const GURL& url,
547                                           net::FakeURLFetcher* fetcher) {
548   scoped_refptr<net::HttpResponseHeaders> download_headers =
549       new net::HttpResponseHeaders(kExampleJobDownloadResponseHeaders);
550   fetcher->set_response_headers(download_headers);
551 }
552 
AddTicketMimeHeader(const GURL & url,net::FakeURLFetcher * fetcher)553 void PrinterJobHandlerTest::AddTicketMimeHeader(const GURL& url,
554                                                 net::FakeURLFetcher* fetcher) {
555   scoped_refptr<net::HttpResponseHeaders> download_headers =
556       new net::HttpResponseHeaders(kExampleTicketDownloadResponseHeaders);
557   fetcher->set_response_headers(download_headers);
558 }
559 
560 
SetUpJobSuccessTest(int job_num)561 void PrinterJobHandlerTest::SetUpJobSuccessTest(int job_num) {
562   factory_.SetFakeResponse(TicketURI(job_num),
563                            kExamplePrintTicket, net::HTTP_OK,
564                            net::URLRequestStatus::SUCCESS);
565   factory_.SetFakeResponse(DownloadURI(job_num),
566                            kExamplePrintData, net::HTTP_OK,
567                            net::URLRequestStatus::SUCCESS);
568 
569   factory_.SetFakeResponse(DoneURI(job_num),
570                            StatusResponse(job_num, "DONE"),
571                            net::HTTP_OK,
572                            net::URLRequestStatus::SUCCESS);
573   factory_.SetFakeResponse(InProgressURI(job_num),
574                            StatusResponse(job_num, "IN_PROGRESS"),
575                            net::HTTP_OK,
576                            net::URLRequestStatus::SUCCESS);
577 
578   // The times requirement is relaxed for the ticket URI
579   // in order to accommodate TicketDownloadFailureTest
580   EXPECT_CALL(url_callback_, OnRequestCreate(TicketURI(job_num), _))
581       .Times(AtLeast(1))
582       .WillOnce(Invoke(this, &PrinterJobHandlerTest::AddTicketMimeHeader));
583 
584   EXPECT_CALL(url_callback_, OnRequestCreate(DownloadURI(job_num), _))
585       .Times(Exactly(1))
586       .WillOnce(Invoke(this, &PrinterJobHandlerTest::AddMimeHeader));
587 
588   EXPECT_CALL(url_callback_, OnRequestCreate(InProgressURI(job_num), _))
589       .Times(Exactly(1));
590 
591   EXPECT_CALL(url_callback_, OnRequestCreate(DoneURI(job_num), _))
592       .Times(Exactly(1));
593 
594   EXPECT_CALL(print_system_->JobSpooler(),
595               Spool(kExamplePrintTicket, _, _, _, _, _, _, _))
596       .Times(Exactly(1))
597       .WillOnce(InvokeWithoutArgs(this,
598                                   &PrinterJobHandlerTest::PostSpoolSuccess));
599 }
600 
BeginTest(int timeout_seconds)601 void PrinterJobHandlerTest::BeginTest(int timeout_seconds) {
602   job_handler_ = new PrinterJobHandler(basic_info_,
603                                        info_from_cloud_,
604                                        GURL(kExampleCloudPrintServerURL),
605                                        print_system_.get(),
606                                        &jobhandler_delegate_);
607 
608   job_handler_->Initialize();
609 
610   base::MessageLoop::current()->PostDelayedTask(
611       FROM_HERE,
612       base::Bind(&PrinterJobHandlerTest::MessageLoopQuitSoonHelper,
613                  base::MessageLoop::current()),
614       base::TimeDelta::FromSeconds(timeout_seconds));
615 
616   base::MessageLoop::current()->Run();
617 }
618 
SendCapsAndDefaults(const std::string & printer_name,const PrintSystem::PrinterCapsAndDefaultsCallback & callback)619 void PrinterJobHandlerTest::SendCapsAndDefaults(
620     const std::string& printer_name,
621     const PrintSystem::PrinterCapsAndDefaultsCallback& callback) {
622   callback.Run(true, printer_name, caps_and_defaults_);
623 }
624 
GetPrinterInfo(printing::PrinterBasicInfo * info)625 bool PrinterJobHandlerTest::GetPrinterInfo(printing::PrinterBasicInfo* info) {
626   *info = basic_info_;
627   return true;
628 }
629 
TearDown()630 void PrinterJobHandlerTest::TearDown() {
631   IdleOut();
632   CloudPrintURLFetcher::set_factory(NULL);
633 }
634 
IdleOut()635 void PrinterJobHandlerTest::IdleOut() {
636   base::MessageLoop::current()->RunUntilIdle();
637 }
638 
MockPrintServerWatcher()639 MockPrintServerWatcher::MockPrintServerWatcher() : delegate_(NULL) {
640   ON_CALL(*this, StartWatching(_))
641       .WillByDefault(DoAll(SaveArg<0>(&delegate_), Return(true)));
642   ON_CALL(*this, StopWatching()).WillByDefault(Return(true));
643 }
644 
645 
MockPrinterWatcher()646 MockPrinterWatcher::MockPrinterWatcher() : delegate_(NULL) {
647   ON_CALL(*this, StartWatching(_))
648       .WillByDefault(DoAll(SaveArg<0>(&delegate_), Return(true)));
649   ON_CALL(*this, StopWatching()).WillByDefault(Return(true));
650 }
651 
MockJobSpooler()652 MockJobSpooler::MockJobSpooler() : delegate_(NULL) {
653   ON_CALL(*this, Spool(_, _, _, _, _, _, _, _))
654       .WillByDefault(DoAll(SaveArg<7>(&delegate_), Return(true)));
655 }
656 
MockPrintSystem()657 MockPrintSystem::MockPrintSystem()
658     : job_spooler_(new NiceMock<MockJobSpooler>()),
659       printer_watcher_(new NiceMock<MockPrinterWatcher>()),
660       print_server_watcher_(new NiceMock<MockPrintServerWatcher>()) {
661   ON_CALL(*this, CreateJobSpooler()).WillByDefault(Return(job_spooler_.get()));
662 
663   ON_CALL(*this, CreatePrinterWatcher(_))
664       .WillByDefault(Return(printer_watcher_.get()));
665 
666   ON_CALL(*this, CreatePrintServerWatcher())
667       .WillByDefault(Return(print_server_watcher_.get()));
668 
669   ON_CALL(*this, IsValidPrinter(_)).
670       WillByDefault(Return(true));
671 
672   ON_CALL(*this, ValidatePrintTicket(_, _, _)).
673       WillByDefault(Return(true));
674 };
675 
676 // This test simulates an end-to-end printing of a document
677 // but tests only non-failure cases.
678 // Disabled - http://crbug.com/184245
TEST_F(PrinterJobHandlerTest,DISABLED_HappyPathTest)679 TEST_F(PrinterJobHandlerTest, DISABLED_HappyPathTest) {
680   factory_.SetFakeResponse(JobListURI(kJobFetchReasonStartup),
681                            JobListResponse(1), net::HTTP_OK,
682                            net::URLRequestStatus::SUCCESS);
683   factory_.SetFakeResponse(JobListURI(kJobFetchReasonQueryMore),
684                            JobListResponse(0), net::HTTP_OK,
685                            net::URLRequestStatus::SUCCESS);
686 
687   EXPECT_CALL(url_callback_,
688               OnRequestCreate(JobListURI(kJobFetchReasonStartup), _))
689       .Times(Exactly(1));
690   EXPECT_CALL(url_callback_,
691               OnRequestCreate(JobListURI(kJobFetchReasonQueryMore), _))
692       .Times(Exactly(1));
693 
694   SetUpJobSuccessTest(1);
695   BeginTest(20);
696 }
697 
TEST_F(PrinterJobHandlerTest,TicketDownloadFailureTest)698 TEST_F(PrinterJobHandlerTest, TicketDownloadFailureTest) {
699   factory_.SetFakeResponse(JobListURI(kJobFetchReasonStartup),
700                            JobListResponse(2), net::HTTP_OK,
701                            net::URLRequestStatus::SUCCESS);
702   factory_.SetFakeResponse(JobListURI(kJobFetchReasonFailure),
703                            JobListResponse(2), net::HTTP_OK,
704                            net::URLRequestStatus::SUCCESS);
705   factory_.SetFakeResponse(JobListURI(kJobFetchReasonQueryMore),
706                            JobListResponse(0), net::HTTP_OK,
707                            net::URLRequestStatus::SUCCESS);
708   factory_.SetFakeResponse(TicketURI(1), std::string(),
709                            net::HTTP_INTERNAL_SERVER_ERROR,
710                            net::URLRequestStatus::FAILED);
711 
712   EXPECT_CALL(url_callback_, OnRequestCreate(TicketURI(1), _))
713       .Times(AtLeast(1))
714       .WillOnce(Invoke(this, &PrinterJobHandlerTest::AddTicketMimeHeader));
715 
716   EXPECT_CALL(url_callback_,
717               OnRequestCreate(JobListURI(kJobFetchReasonStartup), _))
718       .Times(AtLeast(1));
719 
720   EXPECT_CALL(url_callback_,
721               OnRequestCreate(JobListURI(kJobFetchReasonQueryMore), _))
722       .Times(AtLeast(1));
723 
724   EXPECT_CALL(url_callback_,
725               OnRequestCreate(JobListURI(kJobFetchReasonFailure), _))
726       .Times(AtLeast(1));
727 
728   SetUpJobSuccessTest(2);
729   BeginTest(20);
730 }
731 
732 // TODO(noamsml): Figure out how to make this test not take 1 second and
733 // re-enable it
TEST_F(PrinterJobHandlerTest,DISABLED_ManyFailureTest)734 TEST_F(PrinterJobHandlerTest, DISABLED_ManyFailureTest) {
735   factory_.SetFakeResponse(JobListURI(kJobFetchReasonStartup),
736                            JobListResponse(1), net::HTTP_OK,
737                            net::URLRequestStatus::SUCCESS);
738   factory_.SetFakeResponse(JobListURI(kJobFetchReasonFailure),
739                            JobListResponse(1), net::HTTP_OK,
740                            net::URLRequestStatus::SUCCESS);
741   factory_.SetFakeResponse(JobListURI(kJobFetchReasonRetry),
742                            JobListResponse(1), net::HTTP_OK,
743                            net::URLRequestStatus::SUCCESS);
744   factory_.SetFakeResponse(JobListURI(kJobFetchReasonQueryMore),
745                            JobListResponse(0), net::HTTP_OK,
746                            net::URLRequestStatus::SUCCESS);
747 
748   EXPECT_CALL(url_callback_,
749               OnRequestCreate(JobListURI(kJobFetchReasonStartup), _))
750       .Times(AtLeast(1));
751 
752   EXPECT_CALL(url_callback_,
753               OnRequestCreate(JobListURI(kJobFetchReasonQueryMore), _))
754       .Times(AtLeast(1));
755 
756   EXPECT_CALL(url_callback_,
757               OnRequestCreate(JobListURI(kJobFetchReasonFailure), _))
758       .Times(AtLeast(1));
759 
760   EXPECT_CALL(url_callback_,
761               OnRequestCreate(JobListURI(kJobFetchReasonRetry), _))
762       .Times(AtLeast(1));
763 
764   SetUpJobSuccessTest(1);
765 
766   factory_.SetFakeResponse(TicketURI(1),
767                            std::string(),
768                            net::HTTP_INTERNAL_SERVER_ERROR,
769                            net::URLRequestStatus::FAILED);
770 
771   loop_.PostDelayedTask(FROM_HERE,
772                         base::Bind(&net::FakeURLFetcherFactory::SetFakeResponse,
773                                    base::Unretained(&factory_),
774                                    TicketURI(1),
775                                    kExamplePrintTicket,
776                                    net::HTTP_OK,
777                                    net::URLRequestStatus::SUCCESS),
778                         base::TimeDelta::FromSeconds(1));
779 
780 
781   BeginTest(5);
782 }
783 
784 
785 // TODO(noamsml): Figure out how to make this test not take ~64-~2048 (depending
786 // constant values) seconds and re-enable it
TEST_F(PrinterJobHandlerTest,DISABLED_CompleteFailureTest)787 TEST_F(PrinterJobHandlerTest, DISABLED_CompleteFailureTest) {
788   factory_.SetFakeResponse(JobListURI(kJobFetchReasonStartup),
789                            JobListResponse(1), net::HTTP_OK,
790                            net::URLRequestStatus::SUCCESS);
791   factory_.SetFakeResponse(JobListURI(kJobFetchReasonFailure),
792                            JobListResponse(1), net::HTTP_OK,
793                            net::URLRequestStatus::SUCCESS);
794   factory_.SetFakeResponse(JobListURI(kJobFetchReasonRetry),
795                            JobListResponse(1), net::HTTP_OK,
796                            net::URLRequestStatus::SUCCESS);
797   factory_.SetFakeResponse(ErrorURI(1), StatusResponse(1, "ERROR"),
798                            net::HTTP_OK, net::URLRequestStatus::SUCCESS);
799   factory_.SetFakeResponse(TicketURI(1), std::string(),
800                            net::HTTP_INTERNAL_SERVER_ERROR,
801                            net::URLRequestStatus::FAILED);
802 
803   EXPECT_CALL(url_callback_,
804               OnRequestCreate(JobListURI(kJobFetchReasonStartup), _))
805       .Times(AtLeast(1));
806 
807   EXPECT_CALL(url_callback_,
808               OnRequestCreate(JobListURI(kJobFetchReasonFailure), _))
809       .Times(AtLeast(1));
810 
811   EXPECT_CALL(url_callback_,
812               OnRequestCreate(JobListURI(kJobFetchReasonRetry), _))
813       .Times(AtLeast(1));
814 
815   EXPECT_CALL(url_callback_, OnRequestCreate(ErrorURI(1), _))
816       .Times(Exactly(1))
817       .WillOnce(InvokeWithoutArgs(
818           this, &PrinterJobHandlerTest::MakeJobFetchReturnNoJobs));
819 
820   EXPECT_CALL(url_callback_, OnRequestCreate(TicketURI(1), _))
821       .Times(AtLeast(kNumRetriesBeforeAbandonJob));
822 
823   BeginTest(70);
824 }
825 
826 }  // namespace cloud_print
827