Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1019)

Side by Side Diff: chromeos/printing/ppd_provider_unittest.cc

Issue 2613683004: Completely rewrite the PpdProvider/PpdCache to use the SCS backend. Along the way, clean it up a l… (Closed)
Patch Set: Address michealpg@ comments Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chromeos/printing/ppd_provider.cc ('k') | chromeos/printing/printer_configuration.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <map>
6 #include <utility>
7
5 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
6 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
7 #include "base/files/scoped_temp_dir.h" 11 #include "base/files/scoped_temp_dir.h"
8 #include "base/logging.h" 12 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h" 13 #include "base/message_loop/message_loop.h"
10 #include "base/run_loop.h" 14 #include "base/run_loop.h"
11 #include "base/single_thread_task_runner.h" 15 #include "base/single_thread_task_runner.h"
12 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/test/test_message_loop.h"
18 #include "base/threading/sequenced_task_runner_handle.h"
13 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
14 #include "chromeos/chromeos_paths.h" 20 #include "chromeos/chromeos_paths.h"
15 #include "chromeos/printing/ppd_cache.h" 21 #include "chromeos/printing/ppd_cache.h"
16 #include "chromeos/printing/ppd_provider.h" 22 #include "chromeos/printing/ppd_provider.h"
17 #include "net/url_request/test_url_request_interceptor.h" 23 #include "net/url_request/test_url_request_interceptor.h"
18 #include "net/url_request/url_request_test_util.h" 24 #include "net/url_request/url_request_test_util.h"
19 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
20 26
21 namespace chromeos { 27 namespace chromeos {
22 namespace printing { 28 namespace printing {
29
23 namespace { 30 namespace {
24 31
25 const char kTestQuirksServer[] = "bogusserver.bogus.com"; 32 // Name of the fake server we're resolving ppds from.
26 const char kTestAPIKey[] = "BOGUSAPIKEY"; 33 const char kPpdServer[] = "bogus.google.com";
27 const char kLocalPpdUrl[] = "/some/path";
28 const char kTestManufacturer[] = "Bogus Printer Corp";
29 const char kTestModel[] = "MegaPrint 9000";
30 // The compressedPPD contents here comes from running the command
31 // echo -n "This is the quirks ppd" | base64
32 const char kQuirksResponse[] =
33 "{\n"
34 " \"compressedPpd\": \"VGhpcyBpcyB0aGUgcXVpcmtzIHBwZA==\",\n"
35 " \"lastUpdatedTime\": \"1\"\n"
36 "}\n";
37 const char kQuirksPpd[] = "This is the quirks ppd";
38
39 // A well-formatted response for a list of ppds from quirks server. This
40 // corresponds to the AvailablePrintersMap returned by QuirksPrinters() below.
41 const char kQuirksListResponse[] =
42 "{\n"
43 " \"manufacturers\": [\n"
44 " {\n"
45 " \"manufacturer\": \"manu_a\",\n"
46 " \"models\": [\n"
47 " \"model_1\",\n"
48 " \"model_2\"\n"
49 " ]\n"
50 " },\n"
51 " {\n"
52 " \"manufacturer\": \"manu_b\",\n"
53 " \"models\": [\n"
54 " \"model_3\",\n"
55 " \"model_1\"\n"
56 " ]\n"
57 " }\n"
58 " ]\n"
59 "}\n";
60
61 // Return an AvailablePrintersMap that matches what's in kQuirksListResponse.
62 PpdProvider::AvailablePrintersMap QuirksPrinters() {
63 return {{"manu_a", {"model_1", "model_2"}},
64 {"manu_b", {"model_3", "model_1"}}};
65 }
66 34
67 class PpdProviderTest : public ::testing::Test { 35 class PpdProviderTest : public ::testing::Test {
68 public: 36 public:
69 PpdProviderTest() 37 PpdProviderTest()
70 : loop_(base::MessageLoop::TYPE_IO), 38 : loop_(base::MessageLoop::TYPE_IO),
71 request_context_getter_( 39 request_context_getter_(new net::TestURLRequestContextGetter(
72 new net::TestURLRequestContextGetter(loop_.task_runner().get())) {} 40 base::MessageLoop::current()->task_runner())) {}
73 41
74 void SetUp() override { 42 void SetUp() override {
75 ASSERT_TRUE(ppd_cache_temp_dir_.CreateUniqueTempDir()); 43 ASSERT_TRUE(ppd_cache_temp_dir_.CreateUniqueTempDir());
44 }
45
46 void TearDown() override { StopFakePpdServer(); }
47
48 // Create and return a provider for a test that uses the given |locale|.
49 scoped_refptr<PpdProvider> CreateProvider(const std::string& locale) {
76 auto provider_options = PpdProvider::Options(); 50 auto provider_options = PpdProvider::Options();
77 provider_options.quirks_server = kTestQuirksServer; 51 provider_options.ppd_server_root = std::string("https://") + kPpdServer;
78 ppd_provider_ = PpdProvider::Create( 52
79 kTestAPIKey, request_context_getter_.get(), loop_.task_runner().get(), 53 return PpdProvider::Create(
80 PpdCache::Create(ppd_cache_temp_dir_.GetPath()), provider_options); 54 locale, request_context_getter_.get(),
81 } 55 PpdCache::Create(ppd_cache_temp_dir_.GetPath(),
56 base::MessageLoop::current()->task_runner()),
57 loop_.task_runner().get(), provider_options);
58 }
59
60 // Create an interceptor that serves a small fileset of ppd server files.
61 void StartFakePpdServer() {
62 ASSERT_TRUE(interceptor_temp_dir_.CreateUniqueTempDir());
63 interceptor_ = base::MakeUnique<net::TestURLRequestInterceptor>(
64 "https", kPpdServer, base::ThreadTaskRunnerHandle::Get(),
65 base::ThreadTaskRunnerHandle::Get());
66 // Use brace initialization to express the desired server contents as "url",
67 // "contents" pairs.
68 std::vector<std::pair<std::string, std::string>> server_contents = {
69 {"metadata/locales.json",
70 R"(["en",
71 "es-mx",
72 "en-gb"])"},
73 {"metadata/index.json",
74 R"([
75 ["printer_a_ref", "printer_a.ppd"],
76 ["printer_b_ref", "printer_b.ppd"],
77 ["printer_c_ref", "printer_c.ppd"]
78 ])"},
79 {"metadata/manufacturers-en.json",
80 R"([
81 ["manufacturer_a_en", "manufacturer_a.json"],
82 ["manufacturer_b_en", "manufacturer_b.json"]
83 ])"},
84 {"metadata/manufacturers-en-gb.json",
85 R"([
86 ["manufacturer_a_en-gb", "manufacturer_a.json"],
87 ["manufacturer_b_en-gb", "manufacturer_b.json"]
88 ])"},
89 {"metadata/manufacturers-es-mx.json",
90 R"([
91 ["manufacturer_a_es-mx", "manufacturer_a.json"],
92 ["manufacturer_b_es-mx", "manufacturer_b.json"]
93 ])"},
94 {"metadata/manufacturer_a.json",
95 R"([
96 ["printer_a", "printer_a_ref"],
97 ["printer_b", "printer_b_ref"]
98 ])"},
99 {"metadata/manufacturer_b.json",
100 R"([
101 ["printer_c", "printer_c_ref"]
102 ])"},
103 {"ppds/printer_a.ppd", "a"},
104 {"ppds/printer_b.ppd", "b"},
105 {"ppds/printer_c.ppd", "c"},
106 {"user_supplied_ppd_directory/user_supplied.ppd", "u"}};
107 int next_file_num = 0;
108 for (const auto& entry : server_contents) {
109 base::FilePath filename = interceptor_temp_dir_.GetPath().Append(
110 base::StringPrintf("%d.json", next_file_num++));
111 ASSERT_EQ(
112 base::WriteFile(filename, entry.second.data(), entry.second.size()),
113 static_cast<int>(entry.second.size()))
114 << "Failed to write temp server file";
115 interceptor_->SetResponse(
116 GURL(base::StringPrintf("https://%s/%s", kPpdServer,
117 entry.first.c_str())),
118 filename);
119 }
120 }
121
122 // Interceptor posts a *task* during destruction that actually unregisters
123 // things. So we have to run the message loop post-interceptor-destruction to
124 // actually unregister the URLs, otherwise they won't *actually* be
125 // unregistered until the next time we invoke the message loop. Which may be
126 // in the middle of the next test.
127 //
128 // Note this is harmless to call if we haven't started a fake ppd server.
129 void StopFakePpdServer() {
130 interceptor_.reset();
131 base::RunLoop().RunUntilIdle();
132 }
133
134 // Capture the result of a ResolveManufacturers() call.
135 void CaptureResolveManufacturers(PpdProvider::CallbackResultCode code,
136 const std::vector<std::string>& data) {
137 captured_resolve_manufacturers_.push_back({code, data});
138 }
139
140 // Capture the result of a ResolvePrinters() call.
141 void CaptureResolvePrinters(PpdProvider::CallbackResultCode code,
142 const std::vector<std::string>& data) {
143 captured_resolve_printers_.push_back({code, data});
144 }
145
146 // Capture the result of a ResolvePpd() call.
147 void CaptureResolvePpd(PpdProvider::CallbackResultCode code,
148 const std::string& contents) {
149 captured_resolve_ppd_.push_back({code, contents});
150 }
151
152 // Discard the result of a ResolvePpd() call.
153 void DiscardResolvePpd(PpdProvider::CallbackResultCode code,
154 const std::string& contents) {}
82 155
83 protected: 156 protected:
157 // Run a ResolveManufacturers run from the given locale, expect to get
158 // results in expected_used_locale.
159 void RunLocalizationTest(const std::string& browser_locale,
160 const std::string& expected_used_locale) {
161 captured_resolve_manufacturers_.clear();
162 auto provider = CreateProvider(browser_locale);
163 provider->ResolveManufacturers(base::Bind(
164 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
165 base::RunLoop().RunUntilIdle();
166 provider = nullptr;
167 ASSERT_EQ(captured_resolve_manufacturers_.size(), 1UL);
168 EXPECT_EQ(captured_resolve_manufacturers_[0].first, PpdProvider::SUCCESS);
169
170 const auto& result_vec = captured_resolve_manufacturers_[0].second;
171
172 // It's sufficient to check for one of the expected locale keys to make sure
173 // we got the right map.
174 EXPECT_FALSE(std::find(result_vec.begin(), result_vec.end(),
175 "manufacturer_a_" + expected_used_locale) ==
176 result_vec.end());
177 }
178
179 // Drain tasks both on the loop we use for network/disk activity and the
180 // top-level loop that we're using in the test itself. Unfortunately, even
181 // thought the TestURLRequestContextGetter tells the url fetcher to run on the
182 // current message loop, some deep backend processes can get put into other
183 // loops, which means we can't just trust RunLoop::RunUntilIdle() to drain
184 // outstanding work.
185 void Drain(const PpdProvider& provider) {
186 do {
187 base::RunLoop().RunUntilIdle();
188 } while (!provider.Idle());
189 }
190
191 // Message loop that runs on the current thread.
192 base::TestMessageLoop loop_;
193
194 std::vector<
195 std::pair<PpdProvider::CallbackResultCode, std::vector<std::string>>>
196 captured_resolve_manufacturers_;
197
198 std::vector<
199 std::pair<PpdProvider::CallbackResultCode, std::vector<std::string>>>
200 captured_resolve_printers_;
201
202 std::vector<std::pair<PpdProvider::CallbackResultCode, std::string>>
203 captured_resolve_ppd_;
204
205 std::unique_ptr<net::TestURLRequestInterceptor> interceptor_;
206
84 base::ScopedTempDir ppd_cache_temp_dir_; 207 base::ScopedTempDir ppd_cache_temp_dir_;
208 base::ScopedTempDir interceptor_temp_dir_;
85 209
86 // Provider to be used in the test. 210 // Provider to be used in the test.
87 std::unique_ptr<PpdProvider> ppd_provider_; 211 scoped_refptr<PpdProvider> ppd_provider_;
88 212
89 // Misc extra stuff needed for the test environment to function. 213 // Misc extra stuff needed for the test environment to function.
90 base::MessageLoop loop_; 214 // base::TestMessageLoop loop_;
91 scoped_refptr<net::URLRequestContextGetter> request_context_getter_; 215 scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
92 }; 216 };
93 217
94 // Struct that just captures the callback result for a PpdProvider lookup and 218 // Test that we get back manufacturer maps as expected.
95 // saves it for inspection by the test. 219 TEST_F(PpdProviderTest, ManufacturersFetch) {
96 struct CapturedResolveResult { 220 StartFakePpdServer();
97 bool initialized = false; 221 auto provider = CreateProvider("en");
98 PpdProvider::CallbackResultCode result; 222 // Issue two requests at the same time, both should be resolved properly.
99 base::FilePath file; 223 provider->ResolveManufacturers(base::Bind(
100 }; 224 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
101 225 provider->ResolveManufacturers(base::Bind(
102 // Callback for saving a resolve callback. 226 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
103 void CaptureResolveResultCallback(CapturedResolveResult* capture, 227 Drain(*provider);
104 PpdProvider::CallbackResultCode result, 228 ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
105 base::FilePath file) { 229 std::vector<std::string> expected_result(
106 capture->initialized = true; 230 {"manufacturer_a_en", "manufacturer_b_en"});
107 capture->result = result; 231 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[0].first);
108 capture->file = file; 232 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_manufacturers_[1].first);
109 } 233 EXPECT_TRUE(captured_resolve_manufacturers_[0].second == expected_result);
110 234 EXPECT_TRUE(captured_resolve_manufacturers_[1].second == expected_result);
111 // For a resolve result that should end up successful, check that it is 235 }
112 // successful and the contents are expected_contents. 236
113 void CheckResolveSuccessful(const CapturedResolveResult& captured, 237 // Test that we get a reasonable error when we have no server to contact. Tis
114 const std::string& expected_contents) { 238 // is almost exactly the same as the above test, we just don't bring up the fake
115 ASSERT_TRUE(captured.initialized); 239 // server first.
116 EXPECT_EQ(PpdProvider::SUCCESS, captured.result); 240 TEST_F(PpdProviderTest, ManufacturersFetchNoServer) {
117 241 auto provider = CreateProvider("en");
118 std::string contents; 242 // Issue two requests at the same time, both should be resolved properly.
119 ASSERT_TRUE(base::ReadFileToString(captured.file, &contents)); 243 provider->ResolveManufacturers(base::Bind(
120 EXPECT_EQ(expected_contents, contents); 244 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
121 } 245 provider->ResolveManufacturers(base::Bind(
122 246 &PpdProviderTest::CaptureResolveManufacturers, base::Unretained(this)));
123 // Resolve a PPD via the quirks server. 247 Drain(*provider);
124 TEST_F(PpdProviderTest, QuirksServerResolve) { 248 ASSERT_EQ(2UL, captured_resolve_manufacturers_.size());
249 EXPECT_EQ(PpdProvider::SERVER_ERROR,
250 captured_resolve_manufacturers_[0].first);
251 EXPECT_EQ(PpdProvider::SERVER_ERROR,
252 captured_resolve_manufacturers_[1].first);
253 EXPECT_TRUE(captured_resolve_manufacturers_[0].second.empty());
254 EXPECT_TRUE(captured_resolve_manufacturers_[1].second.empty());
255 }
256
257 // Test that we get things in the requested locale, and that fallbacks are sane.
258 TEST_F(PpdProviderTest, LocalizationAndFallbacks) {
259 StartFakePpdServer();
260 RunLocalizationTest("en-gb", "en-gb");
261 RunLocalizationTest("en-blah", "en");
262 RunLocalizationTest("en-gb-foo", "en-gb");
263 RunLocalizationTest("es", "es-mx");
264 RunLocalizationTest("bogus", "en");
265 }
266
267 // For convenience a null ResolveManufacturers callback target.
268 void ResolveManufacturersNop(PpdProvider::CallbackResultCode code,
269 const std::vector<std::string>& v) {}
270
271 // Test basic ResolvePrinters() functionality. At the same time, make
272 // sure we can get the PpdReference for each of the resolved printers.
273 TEST_F(PpdProviderTest, ResolvePrinters) {
274 StartFakePpdServer();
275 auto provider = CreateProvider("en");
276
277 // Grab the manufacturer list, but don't bother to save it, we know what
278 // should be in it and we check that elsewhere. We just need to run the
279 // resolve to populate the internal PpdProvider structures.
280 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
281 Drain(*provider);
282
283 provider->ResolvePrinters("manufacturer_a_en",
284 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
285 base::Unretained(this)));
286 provider->ResolvePrinters("manufacturer_b_en",
287 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
288 base::Unretained(this)));
289 Drain(*provider);
290 ASSERT_EQ(2UL, captured_resolve_printers_.size());
291 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[0].first);
292 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[1].first);
293 EXPECT_EQ(2UL, captured_resolve_printers_[0].second.size());
294 EXPECT_EQ(std::vector<std::string>({"printer_a", "printer_b"}),
295 captured_resolve_printers_[0].second);
296 EXPECT_EQ(std::vector<std::string>({"printer_c"}),
297 captured_resolve_printers_[1].second);
298
299 // We have manufacturers and models, we should be able to get a ppd out of
300 // this.
301 Printer::PpdReference ref;
302 ASSERT_TRUE(
303 provider->GetPpdReference("manufacturer_a_en", "printer_b", &ref));
304 }
305
306 // Test that if we give a bad reference to ResolvePrinters(), we get an
307 // INTERNAL_ERROR.
308 TEST_F(PpdProviderTest, ResolvePrintersBadReference) {
309 StartFakePpdServer();
310 auto provider = CreateProvider("en");
311 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
312 Drain(*provider);
313
314 provider->ResolvePrinters("bogus_doesnt_exist",
315 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
316 base::Unretained(this)));
317 Drain(*provider);
318 ASSERT_EQ(1UL, captured_resolve_printers_.size());
319 EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_printers_[0].first);
320 }
321
322 // Test that if the server is unavailable, we get SERVER_ERRORs back out.
323 TEST_F(PpdProviderTest, ResolvePrintersNoServer) {
324 StartFakePpdServer();
325 auto provider = CreateProvider("en");
326 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
327 Drain(*provider);
328
329 StopFakePpdServer();
330
331 provider->ResolvePrinters("manufacturer_a_en",
332 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
333 base::Unretained(this)));
334 provider->ResolvePrinters("manufacturer_b_en",
335 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
336 base::Unretained(this)));
337 Drain(*provider);
338 ASSERT_EQ(2UL, captured_resolve_printers_.size());
339 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[0].first);
340 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[1].first);
341 }
342
343 // Test a successful ppd resolution from an effective_make_and_model reference.
344 TEST_F(PpdProviderTest, ResolveServerKeyPpd) {
345 StartFakePpdServer();
346 auto provider = CreateProvider("en");
347 Printer::PpdReference ref;
348 ref.effective_make_and_model = "printer_b_ref";
349 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
350 base::Unretained(this)));
351 ref.effective_make_and_model = "printer_c_ref";
352 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
353 base::Unretained(this)));
354 Drain(*provider);
355
356 ASSERT_EQ(2UL, captured_resolve_ppd_.size());
357 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
358 EXPECT_EQ("b", captured_resolve_ppd_[0].second);
359 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[1].first);
360 EXPECT_EQ("c", captured_resolve_ppd_[1].second);
361 }
362
363 // Test that we *don't* resolve a ppd URL over non-file schemes. It's not clear
364 // whether we'll want to do this in the long term, but for now this is
365 // disallowed because we're not sure we completely understand the security
366 // implications.
367 TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromNetworkFails) {
368 StartFakePpdServer();
369 auto provider = CreateProvider("en");
370
371 Printer::PpdReference ref;
372 ref.user_supplied_ppd_url = base::StringPrintf(
373 "https://%s/user_supplied_ppd_directory/user_supplied.ppd", kPpdServer);
374 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
375 base::Unretained(this)));
376 Drain(*provider);
377
378 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
379 EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_ppd_[0].first);
380 EXPECT_TRUE(captured_resolve_ppd_[0].second.empty());
381 }
382
383 // Test a successful ppd resolution from a user_supplied_url field when
384 // reading from a file. Note we shouldn't need the server to be up
385 // to do this successfully, as we should be able to do this offline.
386 TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpdFromFile) {
387 auto provider = CreateProvider("en");
125 base::ScopedTempDir temp_dir; 388 base::ScopedTempDir temp_dir;
126 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 389 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
127 390 base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
128 Printer::PpdReference ppd_reference; 391
129 ppd_reference.effective_manufacturer = kTestManufacturer; 392 std::string user_ppd_contents = "Woohoo";
130 ppd_reference.effective_model = kTestModel; 393
131 394 ASSERT_EQ(base::WriteFile(filename, user_ppd_contents.data(),
132 { 395 user_ppd_contents.size()),
133 net::TestURLRequestInterceptor interceptor( 396 static_cast<int>(user_ppd_contents.size()));
134 "https", kTestQuirksServer, base::ThreadTaskRunnerHandle::Get(), 397
135 base::ThreadTaskRunnerHandle::Get()); 398 Printer::PpdReference ref;
136 399 ref.user_supplied_ppd_url =
137 GURL expected_url(base::StringPrintf( 400 base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
138 "https://%s/v2/printer/manufacturers/%s/models/%s?key=%s", 401 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
139 kTestQuirksServer, kTestManufacturer, kTestModel, kTestAPIKey)); 402 base::Unretained(this)));
140 403 Drain(*provider);
141 base::FilePath contents_path = temp_dir.GetPath().Append("response"); 404
142 std::string contents = kQuirksResponse; 405 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
143 int bytes_written = 406 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
144 base::WriteFile(contents_path, contents.data(), contents.size()); 407 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].second);
145 ASSERT_EQ(bytes_written, static_cast<int>(contents.size())); 408 }
146 409
147 interceptor.SetResponse(expected_url, contents_path); 410 // Test that we cache ppd resolutions when we fetch them and that we can resolve
148 411 // from the cache without the server available.
149 CapturedResolveResult captured; 412 TEST_F(PpdProviderTest, ResolvedPpdsGetCached) {
150 ppd_provider_->Resolve(ppd_reference, 413 auto provider = CreateProvider("en");
151 base::Bind(CaptureResolveResultCallback, &captured)); 414 std::string user_ppd_contents = "Woohoo";
152 base::RunLoop().RunUntilIdle(); 415 Printer::PpdReference ref;
153 CheckResolveSuccessful(captured, kQuirksPpd);
154 }
155
156 // Now that the interceptor is out of scope, re-run the query. We should
157 // hit in the cache, and thus *not* re-run the query.
158 CapturedResolveResult captured;
159 ppd_provider_->Resolve(ppd_reference,
160 base::Bind(CaptureResolveResultCallback, &captured));
161 base::RunLoop().RunUntilIdle();
162 CheckResolveSuccessful(captured, kQuirksPpd);
163 }
164
165 // Test storage and retrieval of PPDs that are added manually. Even though we
166 // supply a manufacturer and model, we should *not* hit the network for this
167 // resolution since we should find the stored version already cached.
168 TEST_F(PpdProviderTest, LocalResolve) {
169 Printer::PpdReference ppd_reference;
170 ppd_reference.user_supplied_ppd_url = kLocalPpdUrl;
171 ppd_reference.effective_manufacturer = kTestManufacturer;
172 ppd_reference.effective_model = kTestModel;
173
174 // Initially, should not resolve.
175 {
176 CapturedResolveResult captured;
177 ppd_provider_->Resolve(ppd_reference,
178 base::Bind(CaptureResolveResultCallback, &captured));
179 base::RunLoop().RunUntilIdle();
180 EXPECT_TRUE(captured.initialized);
181 EXPECT_EQ(PpdProvider::NOT_FOUND, captured.result);
182 }
183
184 // Store a local ppd.
185 const std::string kLocalPpdContents("My local ppd contents");
186 { 416 {
187 base::ScopedTempDir temp_dir; 417 base::ScopedTempDir temp_dir;
188 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 418 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
189 419 base::FilePath filename = temp_dir.GetPath().Append("my_spiffy.ppd");
190 base::FilePath local_ppd_path = temp_dir.GetPath().Append("local_ppd"); 420
191 ASSERT_EQ(base::WriteFile(local_ppd_path, kLocalPpdContents.data(), 421 ASSERT_EQ(base::WriteFile(filename, user_ppd_contents.data(),
192 kLocalPpdContents.size()), 422 user_ppd_contents.size()),
193 static_cast<int>(kLocalPpdContents.size())); 423 static_cast<int>(user_ppd_contents.size()));
194 ASSERT_TRUE(ppd_provider_->CachePpd(ppd_reference, local_ppd_path)); 424
195 } 425 ref.user_supplied_ppd_url =
196 // temp_dir should now be deleted, which helps make sure we actually latched a 426 base::StringPrintf("file://%s", filename.MaybeAsASCII().c_str());
197 // copy, not a reference. 427 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
198 428 base::Unretained(this)));
199 // Retry the resove, should get the PPD back now. 429 Drain(*provider);
200 { 430
201 CapturedResolveResult captured; 431 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
202 432 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
203 ppd_provider_->Resolve(ppd_reference, 433 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].second);
204 base::Bind(CaptureResolveResultCallback, &captured)); 434 }
205 base::RunLoop().RunUntilIdle(); 435 // ScopedTempDir goes out of scope, so the source file should now be
206 CheckResolveSuccessful(captured, kLocalPpdContents); 436 // deleted. But if we resolve again, we should hit the cache and
207 } 437 // still be successful.
208 } 438
209 439 captured_resolve_ppd_.clear();
210 // Run a query for the list of available printers. 440
211 TEST_F(PpdProviderTest, QueryAvailable) { 441 // Recreate the provider to make sure we don't have any memory caches which
212 base::ScopedTempDir temp_dir; 442 // would mask problems with disk persistence.
213 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 443 provider = CreateProvider("en");
214 PpdProvider::CallbackResultCode result_code; 444
215 PpdProvider::AvailablePrintersMap available_printers; 445 // Re-resolve.
216 446 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
217 // Define a callback that sets the above variables with the callback results. 447 base::Unretained(this)));
218 // This would be cleaner with capture groups, but Bind disallows them in 448 Drain(*provider);
219 // lambdas. 449
220 PpdProvider::QueryAvailableCallback query_callback = base::Bind( 450 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
221 [](PpdProvider::CallbackResultCode* code_out, 451 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
222 PpdProvider::AvailablePrintersMap* query_result_out, 452 EXPECT_EQ(user_ppd_contents, captured_resolve_ppd_[0].second);
223 PpdProvider::CallbackResultCode code,
224 const PpdProvider::AvailablePrintersMap& query_result) {
225 *code_out = code;
226 *query_result_out = query_result;
227 },
228 &result_code, &available_printers);
229
230 {
231 net::TestURLRequestInterceptor interceptor(
232 "https", kTestQuirksServer, base::ThreadTaskRunnerHandle::Get(),
233 base::ThreadTaskRunnerHandle::Get());
234
235 GURL expected_url(base::StringPrintf("https://%s/v2/printer/list?key=%s",
236 kTestQuirksServer, kTestAPIKey));
237
238 base::FilePath contents_path = temp_dir.GetPath().Append("response");
239 std::string contents = kQuirksListResponse;
240 int bytes_written = base::WriteFile(contents_path, kQuirksListResponse,
241 strlen(kQuirksListResponse));
242 ASSERT_EQ(static_cast<int>(strlen(kQuirksListResponse)), bytes_written);
243
244 interceptor.SetResponse(expected_url, contents_path);
245
246 CapturedResolveResult captured;
247 ppd_provider_->QueryAvailable(query_callback);
248 base::RunLoop().RunUntilIdle();
249 EXPECT_EQ(PpdProvider::SUCCESS, result_code);
250 EXPECT_EQ(QuirksPrinters(), available_printers);
251 }
252
253 // Now that the interceptor is out of scope, re-run the query. We should
254 // hit in the cache, and thus *not* re-run the query. Reset the capture
255 // variables first.
256 result_code = PpdProvider::SERVER_ERROR;
257 available_printers.clear();
258 ppd_provider_->QueryAvailable(query_callback);
259 base::RunLoop().RunUntilIdle();
260 EXPECT_EQ(PpdProvider::SUCCESS, result_code);
261 EXPECT_EQ(QuirksPrinters(), available_printers);
262 } 453 }
263 454
264 } // namespace 455 } // namespace
265 } // namespace printing 456 } // namespace printing
266 } // namespace chromeos 457 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/printing/ppd_provider.cc ('k') | chromeos/printing/printer_configuration.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698