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 "chrome/service/cloud_print/printer_job_queue_handler.h"
6
7#include <set>
8
9#include "base/json/json_reader.h"
10#include "base/values.h"
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14using ::testing::Return;
15using ::testing::AtLeast;
16
17namespace cloud_print {
18
19const char kJobListResponse[] =
20    "{"
21    " \"success\" : true, "
22    " \"jobs\" : ["
23    "{"
24    "  \"tags\" : [ \"^own\", \"\"], "
25    "  \"title\" : \"test1\","
26    "  \"ticketUrl\" : \"http://example.com/job1ticket\","
27    "  \"fileUrl\" : \"http://example.com/job1data\","
28    "  \"id\" : \"__testjob1\""
29    "},"
30    "{"
31    "  \"tags\" : [ \"^own\", \"\"], "
32    "  \"title\" : \"test2\","
33    "  \"ticketUrl\" : \"http://example.com/job2ticket\","
34    "  \"fileUrl\" : \"http://example.com/job2data\","
35    "  \"id\" : \"__testjob2\""
36    "},"
37    "{"
38    "  \"tags\" : [ \"^own\", \"\"], "
39    "  \"title\" : \"test3\","
40    "  \"ticketUrl\" : \"http://example.com/job3ticket\","
41    "  \"fileUrl\" : \"http://example.com/job3data\","
42    "  \"id\" : \"__testjob3\""
43    "}"
44    "]"
45    "}";
46
47class TimeProviderMock : public PrinterJobQueueHandler::TimeProvider {
48 public:
49  MOCK_METHOD0(GetNow, base::Time());
50};
51
52class PrinterJobQueueHandlerTest : public ::testing::Test {
53 protected:
54  base::Value* data_;
55  base::DictionaryValue* json_data_;
56  virtual void SetUp() {
57    base::JSONReader json_reader;
58    data_ = json_reader.Read(kJobListResponse);
59    data_->GetAsDictionary(&json_data_);
60  }
61
62  virtual void TearDown() {
63    delete data_;
64  }
65};
66
67TEST_F(PrinterJobQueueHandlerTest, BasicJobReadTest) {
68  PrinterJobQueueHandler job_queue_handler;
69  std::vector<JobDetails> jobs;
70
71  job_queue_handler.GetJobsFromQueue(json_data_, &jobs);
72
73  ASSERT_EQ((size_t)3, jobs.size());
74
75  EXPECT_EQ(std::string("__testjob1"), jobs[0].job_id_);
76  EXPECT_EQ(std::string("test1"), jobs[0].job_title_);
77  EXPECT_EQ(std::string("http://example.com/job1ticket"),
78            jobs[0].print_ticket_url_);
79  EXPECT_EQ(std::string("http://example.com/job1data"),
80            jobs[0].print_data_url_);
81
82  std::set<std::string> expected_tags;
83  expected_tags.insert("^own");
84  expected_tags.insert(std::string());
85  std::set<std::string> actual_tags;
86  actual_tags.insert(jobs[0].tags_.begin(), jobs[0].tags_.end());
87
88  EXPECT_EQ(expected_tags, actual_tags);
89  EXPECT_EQ(base::TimeDelta(), jobs[0].time_remaining_);
90}
91
92TEST_F(PrinterJobQueueHandlerTest, PreferNonFailureTest) {
93  TimeProviderMock* time_mock = new TimeProviderMock();
94  PrinterJobQueueHandler job_queue_handler(time_mock);
95  EXPECT_CALL((*time_mock), GetNow())
96      .Times(AtLeast(2))
97      .WillRepeatedly(Return(base::Time::UnixEpoch()));
98
99  // must fail twice for backoff to kick in
100  job_queue_handler.JobFetchFailed("__testjob1");
101  job_queue_handler.JobFetchFailed("__testjob1");
102
103  std::vector<JobDetails> jobs;
104  job_queue_handler.GetJobsFromQueue(json_data_, &jobs);
105
106  EXPECT_EQ(std::string("__testjob2"), jobs[0].job_id_);
107  EXPECT_EQ(base::TimeDelta(), jobs[0].time_remaining_);
108}
109
110TEST_F(PrinterJobQueueHandlerTest, PreferNoTimeTest) {
111  TimeProviderMock* time_mock = new TimeProviderMock();
112  PrinterJobQueueHandler job_queue_handler(time_mock);
113  EXPECT_CALL((*time_mock), GetNow()).
114      Times(AtLeast(8));
115
116  ON_CALL((*time_mock), GetNow())
117      .WillByDefault(Return(base::Time::UnixEpoch()));
118
119  for (int i = 0; i < 4; i++)
120    job_queue_handler.JobFetchFailed("__testjob1");
121
122  ON_CALL((*time_mock), GetNow())
123      .WillByDefault(Return(base::Time::UnixEpoch() +
124                            base::TimeDelta::FromMinutes(4)));
125
126  for (int i = 0; i < 2; i++)
127    job_queue_handler.JobFetchFailed("__testjob2");
128
129  for (int i = 0; i < 2; i++)
130    job_queue_handler.JobFetchFailed("__testjob3");
131
132  std::vector<JobDetails> jobs;
133  job_queue_handler.GetJobsFromQueue(json_data_, &jobs);
134
135  EXPECT_EQ(base::TimeDelta(), jobs[0].time_remaining_);
136  EXPECT_EQ(std::string("__testjob1"), jobs[0].job_id_);
137}
138
139TEST_F(PrinterJobQueueHandlerTest, PreferLowerTimeTest) {
140  TimeProviderMock* time_mock = new TimeProviderMock();
141  PrinterJobQueueHandler job_queue_handler(time_mock);
142
143  EXPECT_CALL((*time_mock), GetNow()).
144      Times(AtLeast(8));
145
146  ON_CALL((*time_mock), GetNow())
147      .WillByDefault(Return(base::Time::UnixEpoch()));
148
149  for (int i = 0; i < 4; i++)
150    job_queue_handler.JobFetchFailed("__testjob1");
151
152  ON_CALL((*time_mock), GetNow())
153      .WillByDefault(Return(base::Time::UnixEpoch() +
154                            base::TimeDelta::FromSeconds(4)));
155
156  for (int i = 0; i < 2; i++)
157    job_queue_handler.JobFetchFailed("__testjob2");
158
159  for (int i = 0; i < 2; i++)
160    job_queue_handler.JobFetchFailed("__testjob3");
161
162  std::vector<JobDetails> jobs;
163  job_queue_handler.GetJobsFromQueue(json_data_,
164                                                   &jobs);
165
166  base::TimeDelta time_to_wait = jobs[0].time_remaining_;
167  EXPECT_NE(base::TimeDelta(), time_to_wait);
168
169  jobs.clear();
170  ON_CALL((*time_mock), GetNow())
171      .WillByDefault(Return(base::Time::UnixEpoch() +
172                            base::TimeDelta::FromSeconds(4) + time_to_wait));
173
174  job_queue_handler.GetJobsFromQueue(json_data_,
175                                     &jobs);
176
177  EXPECT_EQ(base::TimeDelta(), jobs[0].time_remaining_);
178  EXPECT_EQ(std::string("__testjob2"),  jobs[0].job_id_);
179}
180
181}  // namespace cloud_print
182