1 // Copyright 2015 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.
6 #include "base/json/json_string_value_serializer.h"
7 #include "base/memory/ref_counted_memory.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "extensions/browser/api/printer_provider/printer_provider_api.h"
11 #include "extensions/browser/api/printer_provider/printer_provider_api_factory.h"
12 #include "extensions/browser/api/printer_provider/printer_provider_print_job.h"
13 #include "extensions/browser/extension_registry.h"
14 #include "extensions/common/extension.h"
15 #include "extensions/shell/test/shell_apitest.h"
16 #include "extensions/test/extension_test_message_listener.h"
17 #include "extensions/test/result_catcher.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 using extensions::PrinterProviderAPI
;
23 using extensions::PrinterProviderAPIFactory
;
25 // Callback for PrinterProviderAPI::DispatchGetPrintersRequested calls.
26 // It appends items in |printers| to |*printers_out|. If |done| is set, it runs
28 void AppendPrintersAndRunCallbackIfDone(base::ListValue
* printers_out
,
29 const base::Closure
& callback
,
30 const base::ListValue
& printers
,
32 for (size_t i
= 0; i
< printers
.GetSize(); ++i
) {
33 const base::DictionaryValue
* printer
= NULL
;
34 EXPECT_TRUE(printers
.GetDictionary(i
, &printer
))
35 << "Found invalid printer value at index " << i
<< ": " << printers
;
37 printers_out
->Append(printer
->DeepCopy());
39 if (done
&& !callback
.is_null())
43 // Callback for PrinterProviderAPI::DispatchPrintRequested calls.
44 // It copies |value| to |*result| and runs |callback|.
45 void RecordPrintResultAndRunCallback(bool* result_success
,
46 std::string
* result_status
,
47 const base::Closure
& callback
,
49 const std::string
& status
) {
50 *result_success
= success
;
51 *result_status
= status
;
52 if (!callback
.is_null())
56 // Callback for PrinterProviderAPI::DispatchGetCapabilityRequested calls.
57 // It saves reported |value| as JSON string to |*result| and runs |callback|.
58 void RecordDictAndRunCallback(std::string
* result
,
59 const base::Closure
& callback
,
60 const base::DictionaryValue
& value
) {
61 JSONStringValueSerializer
serializer(result
);
62 EXPECT_TRUE(serializer
.Serialize(value
));
63 if (!callback
.is_null())
67 // Tests for chrome.printerProvider API.
68 class PrinterProviderApiTest
: public extensions::ShellApiTest
{
70 PrinterProviderApiTest() {}
71 ~PrinterProviderApiTest() override
{}
73 void StartGetPrintersRequest(
74 const PrinterProviderAPI::GetPrintersCallback
& callback
) {
75 PrinterProviderAPIFactory::GetInstance()
76 ->GetForBrowserContext(browser_context())
77 ->DispatchGetPrintersRequested(callback
);
80 void StartPrintRequest(const std::string
& extension_id
,
81 const PrinterProviderAPI::PrintCallback
& callback
) {
82 extensions::PrinterProviderPrintJob job
;
83 job
.printer_id
= extension_id
+ ":printer_id";
84 job
.ticket_json
= "{}";
85 job
.content_type
= "content_type";
86 const unsigned char kDocumentBytes
[] = {'b', 'y', 't', 'e', 's', 0};
88 new base::RefCountedBytes(kDocumentBytes
, arraysize(kDocumentBytes
));
90 PrinterProviderAPIFactory::GetInstance()
91 ->GetForBrowserContext(browser_context())
92 ->DispatchPrintRequested(job
, callback
);
95 void StartCapabilityRequest(
96 const std::string
& extension_id
,
97 const PrinterProviderAPI::GetCapabilityCallback
& callback
) {
98 PrinterProviderAPIFactory::GetInstance()
99 ->GetForBrowserContext(browser_context())
100 ->DispatchGetCapabilityRequested(extension_id
+ ":printer_id",
104 // Loads chrome.printerProvider test app and initializes is for test
106 // When the app's background page is loaded, the app will send 'loaded'
107 // message. As a response to the message it will expect string message
108 // specifying the test that should be run. When the app initializes its state
109 // (e.g. registers listener for a chrome.printerProvider event) it will send
110 // message 'ready', at which point the test may be started.
111 // If the app is successfully initialized, |*extension_id_out| will be set to
112 // the loaded extension's id, otherwise it will remain unchanged.
113 void InitializePrinterProviderTestApp(const std::string
& app_path
,
114 const std::string
& test_param
,
115 std::string
* extension_id_out
) {
116 ExtensionTestMessageListener
loaded_listener("loaded", true);
117 ExtensionTestMessageListener
ready_listener("ready", false);
119 const extensions::Extension
* extension
= LoadApp(app_path
);
120 ASSERT_TRUE(extension
);
121 const std::string extension_id
= extension
->id();
123 loaded_listener
.set_extension_id(extension_id
);
124 ready_listener
.set_extension_id(extension_id
);
126 ASSERT_TRUE(loaded_listener
.WaitUntilSatisfied());
128 loaded_listener
.Reply(test_param
);
130 ASSERT_TRUE(ready_listener
.WaitUntilSatisfied());
132 *extension_id_out
= extension_id
;
135 // Runs a test for chrome.printerProvider.onPrintRequested event.
136 // |test_param|: The test that should be run.
137 // |expected_result|: The print result the app is expected to report.
138 void RunPrintRequestTestApp(const std::string
& test_param
,
139 const std::string
& expected_result
) {
140 extensions::ResultCatcher catcher
;
142 std::string extension_id
;
143 InitializePrinterProviderTestApp("api_test/printer_provider/request_print",
144 test_param
, &extension_id
);
145 if (extension_id
.empty())
148 base::RunLoop run_loop
;
150 std::string print_status
;
151 StartPrintRequest(extension_id
,
152 base::Bind(&RecordPrintResultAndRunCallback
, &success
,
153 &print_status
, run_loop
.QuitClosure()));
155 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
158 EXPECT_EQ(expected_result
, print_status
);
159 EXPECT_EQ(expected_result
== "OK", success
);
162 // Runs a test for chrome.printerProvider.onGetCapabilityRequested
164 // |test_param|: The test that should be run.
165 // |expected_result|: The printer capability the app is expected to report.
166 void RunPrinterCapabilitiesRequestTest(const std::string
& test_param
,
167 const std::string
& expected_result
) {
168 extensions::ResultCatcher catcher
;
170 std::string extension_id
;
171 InitializePrinterProviderTestApp(
172 "api_test/printer_provider/request_capability", test_param
,
174 if (extension_id
.empty())
177 base::RunLoop run_loop
;
179 StartCapabilityRequest(
181 base::Bind(&RecordDictAndRunCallback
, &result
, run_loop
.QuitClosure()));
183 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
186 EXPECT_EQ(expected_result
, result
);
189 bool SimulateExtensionUnload(const std::string
& extension_id
) {
190 extensions::ExtensionRegistry
* extension_registry
=
191 extensions::ExtensionRegistry::Get(browser_context());
193 const extensions::Extension
* extension
=
194 extension_registry
->GetExtensionById(
195 extension_id
, extensions::ExtensionRegistry::ENABLED
);
199 extension_registry
->RemoveEnabled(extension_id
);
200 extension_registry
->TriggerOnUnloaded(
201 extension
, extensions::UnloadedExtensionInfo::REASON_TERMINATE
);
205 // Validates that set of printers reported by test apps via
206 // chrome.printerProvider.onGetPritersRequested is the same as the set of
207 // printers in |expected_printers|. |expected_printers| contains list of
208 // printer objects formatted as a JSON string. It is assumed that the values
209 // in |expoected_printers| are unique.
210 void ValidatePrinterListValue(
211 const base::ListValue
& printers
,
212 const std::vector
<std::string
>& expected_printers
) {
213 ASSERT_EQ(expected_printers
.size(), printers
.GetSize());
214 for (size_t i
= 0; i
< expected_printers
.size(); ++i
) {
215 JSONStringValueSerializer
serializer(expected_printers
[i
]);
217 scoped_ptr
<base::Value
> printer_value(
218 serializer
.Deserialize(&error_code
, NULL
));
219 ASSERT_TRUE(printer_value
) << "Failed to deserialize "
220 << expected_printers
[i
] << ": "
221 << "error code " << error_code
;
222 EXPECT_TRUE(printers
.Find(*printer_value
) != printers
.end())
223 << "Unabe to find " << *printer_value
<< " in " << printers
;
228 DISALLOW_COPY_AND_ASSIGN(PrinterProviderApiTest
);
231 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobSuccess
) {
232 RunPrintRequestTestApp("OK", "OK");
235 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobAsyncSuccess
) {
236 RunPrintRequestTestApp("ASYNC_RESPONSE", "OK");
239 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintJobFailed
) {
240 RunPrintRequestTestApp("INVALID_TICKET", "INVALID_TICKET");
243 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, NoPrintEventListener
) {
244 RunPrintRequestTestApp("NO_LISTENER", "FAILED");
247 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
248 PrintRequestInvalidCallbackParam
) {
249 RunPrintRequestTestApp("INVALID_VALUE", "FAILED");
252 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, PrintRequestAppUnloaded
) {
253 extensions::ResultCatcher catcher
;
255 std::string extension_id
;
256 InitializePrinterProviderTestApp("api_test/printer_provider/request_print",
257 "IGNORE_CALLBACK", &extension_id
);
258 ASSERT_FALSE(extension_id
.empty());
260 base::RunLoop run_loop
;
261 bool success
= false;
263 StartPrintRequest(extension_id
,
264 base::Bind(&RecordPrintResultAndRunCallback
, &success
,
265 &status
, run_loop
.QuitClosure()));
267 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
269 ASSERT_TRUE(SimulateExtensionUnload(extension_id
));
272 EXPECT_FALSE(success
);
273 EXPECT_EQ("FAILED", status
);
276 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilitySuccess
) {
277 RunPrinterCapabilitiesRequestTest("OK", "{\"capability\":\"value\"}");
280 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilityAsyncSuccess
) {
281 RunPrinterCapabilitiesRequestTest("ASYNC_RESPONSE",
282 "{\"capability\":\"value\"}");
285 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, EmptyCapability
) {
286 RunPrinterCapabilitiesRequestTest("EMPTY", "{}");
289 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, NoCapabilityEventListener
) {
290 RunPrinterCapabilitiesRequestTest("NO_LISTENER", "{}");
293 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, CapabilityInvalidValue
) {
294 RunPrinterCapabilitiesRequestTest("INVALID_VALUE", "{}");
297 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetCapabilityAppUnloaded
) {
298 extensions::ResultCatcher catcher
;
300 std::string extension_id
;
301 InitializePrinterProviderTestApp(
302 "api_test/printer_provider/request_capability", "IGNORE_CALLBACK",
304 ASSERT_FALSE(extension_id
.empty());
306 base::RunLoop run_loop
;
308 StartCapabilityRequest(
310 base::Bind(&RecordDictAndRunCallback
, &result
, run_loop
.QuitClosure()));
312 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
314 ASSERT_TRUE(SimulateExtensionUnload(extension_id
));
316 EXPECT_EQ("{}", result
);
319 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersSuccess
) {
320 extensions::ResultCatcher catcher
;
322 std::string extension_id
;
323 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
324 "OK", &extension_id
);
325 ASSERT_FALSE(extension_id
.empty());
327 base::RunLoop run_loop
;
328 base::ListValue printers
;
330 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
331 &printers
, run_loop
.QuitClosure()));
333 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
337 std::vector
<std::string
> expected_printers
;
338 expected_printers
.push_back(base::StringPrintf(
340 "\"description\":\"Test printer\","
341 "\"extensionId\":\"%s\","
342 "\"id\":\"%s:printer1\","
343 "\"name\":\"Printer 1\""
345 extension_id
.c_str(), extension_id
.c_str()));
346 expected_printers
.push_back(base::StringPrintf(
348 "\"extensionId\":\"%s\","
349 "\"id\":\"%s:printerNoDesc\","
350 "\"name\":\"Printer 2\""
352 extension_id
.c_str(), extension_id
.c_str()));
354 ValidatePrinterListValue(printers
, expected_printers
);
357 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersAsyncSuccess
) {
358 extensions::ResultCatcher catcher
;
360 std::string extension_id
;
361 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
362 "ASYNC_RESPONSE", &extension_id
);
363 ASSERT_FALSE(extension_id
.empty());
365 base::RunLoop run_loop
;
366 base::ListValue printers
;
368 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
369 &printers
, run_loop
.QuitClosure()));
371 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
375 std::vector
<std::string
> expected_printers
;
376 expected_printers
.push_back(base::StringPrintf(
378 "\"description\":\"Test printer\","
379 "\"extensionId\":\"%s\","
380 "\"id\":\"%s:printer1\","
381 "\"name\":\"Printer 1\""
383 extension_id
.c_str(), extension_id
.c_str()));
385 ValidatePrinterListValue(printers
, expected_printers
);
388 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersTwoExtensions
) {
389 extensions::ResultCatcher catcher
;
391 std::string extension_id_1
;
392 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
393 "OK", &extension_id_1
);
394 ASSERT_FALSE(extension_id_1
.empty());
396 std::string extension_id_2
;
397 InitializePrinterProviderTestApp(
398 "api_test/printer_provider/request_printers_second", "OK",
400 ASSERT_FALSE(extension_id_2
.empty());
402 base::RunLoop run_loop
;
403 base::ListValue printers
;
405 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
406 &printers
, run_loop
.QuitClosure()));
408 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
409 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
413 std::vector
<std::string
> expected_printers
;
414 expected_printers
.push_back(base::StringPrintf(
416 "\"description\":\"Test printer\","
417 "\"extensionId\":\"%s\","
418 "\"id\":\"%s:printer1\","
419 "\"name\":\"Printer 1\""
421 extension_id_1
.c_str(), extension_id_1
.c_str()));
422 expected_printers
.push_back(base::StringPrintf(
424 "\"extensionId\":\"%s\","
425 "\"id\":\"%s:printerNoDesc\","
426 "\"name\":\"Printer 2\""
428 extension_id_1
.c_str(), extension_id_1
.c_str()));
429 expected_printers
.push_back(base::StringPrintf(
431 "\"description\":\"Test printer\","
432 "\"extensionId\":\"%s\","
433 "\"id\":\"%s:printer1\","
434 "\"name\":\"Printer 1\""
436 extension_id_2
.c_str(), extension_id_2
.c_str()));
437 expected_printers
.push_back(base::StringPrintf(
439 "\"extensionId\":\"%s\","
440 "\"id\":\"%s:printerNoDesc\","
441 "\"name\":\"Printer 2\""
443 extension_id_2
.c_str(), extension_id_2
.c_str()));
445 ValidatePrinterListValue(printers
, expected_printers
);
448 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
449 GetPrintersTwoExtensionsBothUnloaded
) {
450 extensions::ResultCatcher catcher
;
452 std::string extension_id_1
;
453 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
454 "IGNORE_CALLBACK", &extension_id_1
);
455 ASSERT_FALSE(extension_id_1
.empty());
457 std::string extension_id_2
;
458 InitializePrinterProviderTestApp(
459 "api_test/printer_provider/request_printers_second", "IGNORE_CALLBACK",
461 ASSERT_FALSE(extension_id_2
.empty());
463 base::RunLoop run_loop
;
464 base::ListValue printers
;
466 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
467 &printers
, run_loop
.QuitClosure()));
469 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
470 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
472 ASSERT_TRUE(SimulateExtensionUnload(extension_id_1
));
473 ASSERT_TRUE(SimulateExtensionUnload(extension_id_2
));
477 EXPECT_TRUE(printers
.empty());
480 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
481 GetPrintersTwoExtensionsOneFails
) {
482 extensions::ResultCatcher catcher
;
484 std::string extension_id_1
;
485 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
486 "NOT_ARRAY", &extension_id_1
);
487 ASSERT_FALSE(extension_id_1
.empty());
489 std::string extension_id_2
;
490 InitializePrinterProviderTestApp(
491 "api_test/printer_provider/request_printers_second", "OK",
493 ASSERT_FALSE(extension_id_2
.empty());
495 base::RunLoop run_loop
;
496 base::ListValue printers
;
498 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
499 &printers
, run_loop
.QuitClosure()));
501 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
502 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
506 std::vector
<std::string
> expected_printers
;
507 expected_printers
.push_back(base::StringPrintf(
509 "\"description\":\"Test printer\","
510 "\"extensionId\":\"%s\","
511 "\"id\":\"%s:printer1\","
512 "\"name\":\"Printer 1\""
514 extension_id_2
.c_str(), extension_id_2
.c_str()));
515 expected_printers
.push_back(base::StringPrintf(
517 "\"extensionId\":\"%s\","
518 "\"id\":\"%s:printerNoDesc\","
519 "\"name\":\"Printer 2\""
521 extension_id_2
.c_str(), extension_id_2
.c_str()));
523 ValidatePrinterListValue(printers
, expected_printers
);
526 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
527 GetPrintersTwoExtensionsOneWithNoListener
) {
528 extensions::ResultCatcher catcher
;
530 std::string extension_id_1
;
531 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
532 "NO_LISTENER", &extension_id_1
);
533 ASSERT_FALSE(extension_id_1
.empty());
535 std::string extension_id_2
;
536 InitializePrinterProviderTestApp(
537 "api_test/printer_provider/request_printers_second", "OK",
539 ASSERT_FALSE(extension_id_2
.empty());
541 base::RunLoop run_loop
;
542 base::ListValue printers
;
544 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
545 &printers
, run_loop
.QuitClosure()));
547 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
548 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
552 std::vector
<std::string
> expected_printers
;
553 expected_printers
.push_back(base::StringPrintf(
555 "\"description\":\"Test printer\","
556 "\"extensionId\":\"%s\","
557 "\"id\":\"%s:printer1\","
558 "\"name\":\"Printer 1\""
560 extension_id_2
.c_str(), extension_id_2
.c_str()));
561 expected_printers
.push_back(base::StringPrintf(
563 "\"extensionId\":\"%s\","
564 "\"id\":\"%s:printerNoDesc\","
565 "\"name\":\"Printer 2\""
567 extension_id_2
.c_str(), extension_id_2
.c_str()));
569 ValidatePrinterListValue(printers
, expected_printers
);
572 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersNoListener
) {
573 extensions::ResultCatcher catcher
;
575 std::string extension_id
;
576 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
577 "NO_LISTENER", &extension_id
);
578 ASSERT_FALSE(extension_id
.empty());
580 base::RunLoop run_loop
;
581 base::ListValue printers
;
583 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
584 &printers
, run_loop
.QuitClosure()));
586 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
590 EXPECT_TRUE(printers
.empty());
593 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersNotArray
) {
594 extensions::ResultCatcher catcher
;
596 std::string extension_id
;
597 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
598 "NOT_ARRAY", &extension_id
);
599 ASSERT_FALSE(extension_id
.empty());
601 base::RunLoop run_loop
;
602 base::ListValue printers
;
604 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
605 &printers
, run_loop
.QuitClosure()));
607 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
611 EXPECT_TRUE(printers
.empty());
614 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
,
615 GetPrintersInvalidPrinterValueType
) {
616 extensions::ResultCatcher catcher
;
618 std::string extension_id
;
619 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
620 "INVALID_PRINTER_TYPE", &extension_id
);
621 ASSERT_FALSE(extension_id
.empty());
623 base::RunLoop run_loop
;
624 base::ListValue printers
;
626 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
627 &printers
, run_loop
.QuitClosure()));
629 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
633 EXPECT_TRUE(printers
.empty());
636 IN_PROC_BROWSER_TEST_F(PrinterProviderApiTest
, GetPrintersInvalidPrinterValue
) {
637 extensions::ResultCatcher catcher
;
639 std::string extension_id
;
640 InitializePrinterProviderTestApp("api_test/printer_provider/request_printers",
641 "INVALID_PRINTER", &extension_id
);
642 ASSERT_FALSE(extension_id
.empty());
644 base::RunLoop run_loop
;
645 base::ListValue printers
;
647 StartGetPrintersRequest(base::Bind(&AppendPrintersAndRunCallbackIfDone
,
648 &printers
, run_loop
.QuitClosure()));
650 ASSERT_TRUE(catcher
.GetNextResult()) << catcher
.message();
654 EXPECT_TRUE(printers
.empty());