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

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 latest skau comments, rebase and make it work with recent sync changes 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
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 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());
125 base::ScopedTempDir temp_dir; 249 EXPECT_EQ(PpdProvider::SERVER_ERROR,
126 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 250 captured_resolve_manufacturers_[0].first);
127 251 EXPECT_EQ(PpdProvider::SERVER_ERROR,
128 Printer::PpdReference ppd_reference; 252 captured_resolve_manufacturers_[1].first);
129 ppd_reference.effective_manufacturer = kTestManufacturer; 253 EXPECT_TRUE(captured_resolve_manufacturers_[0].second.empty());
130 ppd_reference.effective_model = kTestModel; 254 EXPECT_TRUE(captured_resolve_manufacturers_[1].second.empty());
131 255 }
132 { 256
133 net::TestURLRequestInterceptor interceptor( 257 // Test that we get things in the requested locale, and that fallbacks are sane.
134 "https", kTestQuirksServer, base::ThreadTaskRunnerHandle::Get(), 258 TEST_F(PpdProviderTest, LocalizationAndFallbacks) {
135 base::ThreadTaskRunnerHandle::Get()); 259 StartFakePpdServer();
136 260 RunLocalizationTest("en-gb", "en-gb");
137 GURL expected_url(base::StringPrintf( 261 RunLocalizationTest("en-blah", "en");
138 "https://%s/v2/printer/manufacturers/%s/models/%s?key=%s", 262 RunLocalizationTest("en-gb-foo", "en-gb");
139 kTestQuirksServer, kTestManufacturer, kTestModel, kTestAPIKey)); 263 RunLocalizationTest("es", "es-mx");
140 264 RunLocalizationTest("bogus", "en");
141 base::FilePath contents_path = temp_dir.GetPath().Append("response"); 265 }
142 std::string contents = kQuirksResponse; 266
143 int bytes_written = 267 // For convenience a null ResolveManufacturers callback target.
144 base::WriteFile(contents_path, contents.data(), contents.size()); 268 void ResolveManufacturersNop(PpdProvider::CallbackResultCode code,
145 ASSERT_EQ(bytes_written, static_cast<int>(contents.size())); 269 const std::vector<std::string>& v) {}
146 270
147 interceptor.SetResponse(expected_url, contents_path); 271 // Test basic ResolvePrinters() functionality. At the same time, make
148 272 // sure we can get the PpdReference for each of the resolved printers.
149 CapturedResolveResult captured; 273 TEST_F(PpdProviderTest, ResolvePrinters) {
150 ppd_provider_->Resolve(ppd_reference, 274 StartFakePpdServer();
151 base::Bind(CaptureResolveResultCallback, &captured)); 275 auto provider = CreateProvider("en");
152 base::RunLoop().RunUntilIdle(); 276
153 CheckResolveSuccessful(captured, kQuirksPpd); 277 // Grab the manufacturer list, but don't bother to save it, we know what
154 } 278 // should be in it and we check that elsewhere. We just need to run the
155 279 // resolve to populate the internal PpdProvider structures.
156 // Now that the interceptor is out of scope, re-run the query. We should 280 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
157 // hit in the cache, and thus *not* re-run the query. 281 Drain(*provider);
158 CapturedResolveResult captured; 282
159 ppd_provider_->Resolve(ppd_reference, 283 provider->ResolvePrinters("manufacturer_a_en",
160 base::Bind(CaptureResolveResultCallback, &captured)); 284 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
161 base::RunLoop().RunUntilIdle(); 285 base::Unretained(this)));
162 CheckResolveSuccessful(captured, kQuirksPpd); 286 provider->ResolvePrinters("manufacturer_b_en",
163 } 287 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
164 288 base::Unretained(this)));
165 // Test storage and retrieval of PPDs that are added manually. Even though we 289 Drain(*provider);
166 // supply a manufacturer and model, we should *not* hit the network for this 290 ASSERT_EQ(2UL, captured_resolve_printers_.size());
167 // resolution since we should find the stored version already cached. 291 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[0].first);
168 TEST_F(PpdProviderTest, LocalResolve) { 292 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_printers_[1].first);
169 Printer::PpdReference ppd_reference; 293 EXPECT_EQ(2UL, captured_resolve_printers_[0].second.size());
170 ppd_reference.user_supplied_ppd_url = kLocalPpdUrl; 294 EXPECT_EQ(std::vector<std::string>({"printer_a", "printer_b"}),
171 ppd_reference.effective_manufacturer = kTestManufacturer; 295 captured_resolve_printers_[0].second);
172 ppd_reference.effective_model = kTestModel; 296 EXPECT_EQ(std::vector<std::string>({"printer_c"}),
173 297 captured_resolve_printers_[1].second);
174 // Initially, should not resolve. 298
175 { 299 // We have manufacturers and models, we should be able to get a ppd out of
176 CapturedResolveResult captured; 300 // this.
177 ppd_provider_->Resolve(ppd_reference, 301 Printer::PpdReference ref;
178 base::Bind(CaptureResolveResultCallback, &captured)); 302 ASSERT_TRUE(
179 base::RunLoop().RunUntilIdle(); 303 provider->GetPpdReference("manufacturer_a_en", "printer_b", &ref));
180 EXPECT_TRUE(captured.initialized); 304 }
181 EXPECT_EQ(PpdProvider::NOT_FOUND, captured.result); 305
182 } 306 // Test that if we give a bad reference to ResolvePrinters(), we get an
183 307 // INTERNAL_ERROR.
184 // Store a local ppd. 308 TEST_F(PpdProviderTest, ResolvePrintersBadReference) {
185 const std::string kLocalPpdContents("My local ppd contents"); 309 StartFakePpdServer();
186 { 310 auto provider = CreateProvider("en");
187 base::ScopedTempDir temp_dir; 311 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
188 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 312 Drain(*provider);
189 313
190 base::FilePath local_ppd_path = temp_dir.GetPath().Append("local_ppd"); 314 provider->ResolvePrinters("bogus_doesnt_exist",
191 ASSERT_EQ(base::WriteFile(local_ppd_path, kLocalPpdContents.data(), 315 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
192 kLocalPpdContents.size()), 316 base::Unretained(this)));
193 static_cast<int>(kLocalPpdContents.size())); 317 Drain(*provider);
194 ASSERT_TRUE(ppd_provider_->CachePpd(ppd_reference, local_ppd_path)); 318 ASSERT_EQ(1UL, captured_resolve_printers_.size());
195 } 319 EXPECT_EQ(PpdProvider::INTERNAL_ERROR, captured_resolve_printers_[0].first);
196 // temp_dir should now be deleted, which helps make sure we actually latched a 320 }
197 // copy, not a reference. 321
198 322 // Test that if the server is unavailable, we get SERVER_ERRORs back out.
199 // Retry the resove, should get the PPD back now. 323 TEST_F(PpdProviderTest, ResolvePrintersNoServer) {
200 { 324 StartFakePpdServer();
201 CapturedResolveResult captured; 325 auto provider = CreateProvider("en");
202 326 provider->ResolveManufacturers(base::Bind(&ResolveManufacturersNop));
203 ppd_provider_->Resolve(ppd_reference, 327 Drain(*provider);
204 base::Bind(CaptureResolveResultCallback, &captured)); 328
205 base::RunLoop().RunUntilIdle(); 329 StopFakePpdServer();
206 CheckResolveSuccessful(captured, kLocalPpdContents); 330
207 } 331 provider->ResolvePrinters("manufacturer_a_en",
208 } 332 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
209 333 base::Unretained(this)));
210 // Run a query for the list of available printers. 334 provider->ResolvePrinters("manufacturer_b_en",
211 TEST_F(PpdProviderTest, QueryAvailable) { 335 base::Bind(&PpdProviderTest::CaptureResolvePrinters,
212 base::ScopedTempDir temp_dir; 336 base::Unretained(this)));
213 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 337 Drain(*provider);
214 PpdProvider::CallbackResultCode result_code; 338 ASSERT_EQ(2UL, captured_resolve_printers_.size());
215 PpdProvider::AvailablePrintersMap available_printers; 339 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[0].first);
216 340 EXPECT_EQ(PpdProvider::SERVER_ERROR, captured_resolve_printers_[1].first);
217 // Define a callback that sets the above variables with the callback results. 341 }
218 // This would be cleaner with capture groups, but Bind disallows them in 342
219 // lambdas. 343 // Test a successful ppd resolution from an effective_make_and_model reference.
220 PpdProvider::QueryAvailableCallback query_callback = base::Bind( 344 TEST_F(PpdProviderTest, ResolveServerKeyPpd) {
221 [](PpdProvider::CallbackResultCode* code_out, 345 StartFakePpdServer();
222 PpdProvider::AvailablePrintersMap* query_result_out, 346 auto provider = CreateProvider("en");
223 PpdProvider::CallbackResultCode code, 347 Printer::PpdReference ref;
224 const PpdProvider::AvailablePrintersMap& query_result) { 348 ref.effective_make_and_model = "printer_b_ref";
225 *code_out = code; 349 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
226 *query_result_out = query_result; 350 base::Unretained(this)));
227 }, 351 ref.effective_make_and_model = "printer_c_ref";
228 &result_code, &available_printers); 352 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
229 353 base::Unretained(this)));
230 { 354 Drain(*provider);
231 net::TestURLRequestInterceptor interceptor( 355
232 "https", kTestQuirksServer, base::ThreadTaskRunnerHandle::Get(), 356 ASSERT_EQ(2UL, captured_resolve_ppd_.size());
233 base::ThreadTaskRunnerHandle::Get()); 357 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
234 358 EXPECT_EQ("b", captured_resolve_ppd_[0].second);
235 GURL expected_url(base::StringPrintf("https://%s/v2/printer/list?key=%s", 359 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[1].first);
236 kTestQuirksServer, kTestAPIKey)); 360 EXPECT_EQ("c", captured_resolve_ppd_[1].second);
237 361 }
238 base::FilePath contents_path = temp_dir.GetPath().Append("response"); 362
239 std::string contents = kQuirksListResponse; 363 // Test a successful ppd resolution from a user_supplied_url field.
240 int bytes_written = base::WriteFile(contents_path, kQuirksListResponse, 364 TEST_F(PpdProviderTest, ResolveUserSuppliedUrlPpd) {
241 strlen(kQuirksListResponse)); 365 StartFakePpdServer();
242 ASSERT_EQ(static_cast<int>(strlen(kQuirksListResponse)), bytes_written); 366 auto provider = CreateProvider("en");
243 367
244 interceptor.SetResponse(expected_url, contents_path); 368 Printer::PpdReference ref;
245 369 ref.user_supplied_ppd_url = base::StringPrintf(
246 CapturedResolveResult captured; 370 "https://%s/user_supplied_ppd_directory/user_supplied.ppd", kPpdServer);
247 ppd_provider_->QueryAvailable(query_callback); 371 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
248 base::RunLoop().RunUntilIdle(); 372 base::Unretained(this)));
249 EXPECT_EQ(PpdProvider::SUCCESS, result_code); 373 Drain(*provider);
250 EXPECT_EQ(QuirksPrinters(), available_printers); 374
251 } 375 ASSERT_EQ(1UL, captured_resolve_ppd_.size());
252 376 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
253 // Now that the interceptor is out of scope, re-run the query. We should 377 EXPECT_EQ("u", captured_resolve_ppd_[0].second);
254 // hit in the cache, and thus *not* re-run the query. Reset the capture 378 }
255 // variables first. 379
256 result_code = PpdProvider::SERVER_ERROR; 380 // Test that we cache ppd resolutions when we fetch them and that we can resolve
257 available_printers.clear(); 381 // from the cache without the server available.
258 ppd_provider_->QueryAvailable(query_callback); 382 TEST_F(PpdProviderTest, ResolvedPpdsGetCached) {
259 base::RunLoop().RunUntilIdle(); 383 StartFakePpdServer();
260 EXPECT_EQ(PpdProvider::SUCCESS, result_code); 384 auto provider = CreateProvider("en");
261 EXPECT_EQ(QuirksPrinters(), available_printers); 385
386 // We'll use 3 references here, 2 server-key based, 1 user supplied url.
387 std::vector<Printer::PpdReference> refs(3);
388 refs[0].effective_make_and_model = "printer_a_ref";
389 refs[1].user_supplied_ppd_url = base::StringPrintf(
390 "https://%s/user_supplied_ppd_directory/user_supplied.ppd", kPpdServer);
391 refs[2].effective_make_and_model = "printer_b_ref";
392
393 // Resolve three ppds from the server, discarding the results. This should
394 // get the ppds into the cache.
395 for (const Printer::PpdReference& ref : refs) {
396 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::DiscardResolvePpd,
397 base::Unretained(this)));
398 }
399 Drain(*provider);
400
401 // Now take down the server and resolve again. All should succeed. Also
402 // recreate the provider for good measure.
403 StopFakePpdServer();
404 provider = CreateProvider("en");
405
406 // Re-resolve, this time capturing the results.
407 for (const Printer::PpdReference& ref : refs) {
408 provider->ResolvePpd(ref, base::Bind(&PpdProviderTest::CaptureResolvePpd,
409 base::Unretained(this)));
410 }
411 Drain(*provider);
412
413 ASSERT_EQ(3UL, captured_resolve_ppd_.size());
414 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[0].first);
415 EXPECT_EQ("a", captured_resolve_ppd_[0].second);
416 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[1].first);
417 EXPECT_EQ("u", captured_resolve_ppd_[1].second);
418 EXPECT_EQ(PpdProvider::SUCCESS, captured_resolve_ppd_[2].first);
419 EXPECT_EQ("b", captured_resolve_ppd_[2].second);
262 } 420 }
263 421
264 } // namespace 422 } // namespace
265 } // namespace printing 423 } // namespace printing
266 } // namespace chromeos 424 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698