1 // Copyright (c) 2012 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 "printing/backend/cups_helper.h"
6
7 #include "base/strings/stringprintf.h"
8 #include "build/build_config.h"
9 #include "printing/backend/print_backend.h"
10 #include "printing/mojom/print.mojom.h"
11 #include "printing/print_settings.h"
12 #include "printing/printing_utils.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace printing {
17
18 namespace {
19
20 // Returns true if the papers have the same name, vendor ID, and size.
PapersEqual(const PrinterSemanticCapsAndDefaults::Paper & lhs,const PrinterSemanticCapsAndDefaults::Paper & rhs)21 bool PapersEqual(const PrinterSemanticCapsAndDefaults::Paper& lhs,
22 const PrinterSemanticCapsAndDefaults::Paper& rhs) {
23 return lhs.display_name == rhs.display_name &&
24 lhs.vendor_id == rhs.vendor_id && lhs.size_um == rhs.size_um;
25 }
26
VerifyCapabilityColorModels(const PrinterSemanticCapsAndDefaults & caps)27 void VerifyCapabilityColorModels(const PrinterSemanticCapsAndDefaults& caps) {
28 base::Optional<bool> maybe_color = IsColorModelSelected(caps.color_model);
29 ASSERT_TRUE(maybe_color.has_value());
30 EXPECT_TRUE(maybe_color.value());
31 maybe_color = IsColorModelSelected(caps.bw_model);
32 ASSERT_TRUE(maybe_color.has_value());
33 EXPECT_FALSE(maybe_color.value());
34 }
35
GeneratePpdResolutionTestData(const char * res_name)36 std::string GeneratePpdResolutionTestData(const char* res_name) {
37 return base::StringPrintf(R"(*PPD-Adobe: 4.3
38 *OpenUI *%1$s/%1$s: PickOne
39 *%1$s 600dpi/600 dpi: " "
40 *Default%1$s: 600dpi
41 *CloseUI: *%1$s)",
42 res_name);
43 }
44
45 } // namespace
46
TEST(PrintBackendCupsHelperTest,TestPpdParsingNoColorDuplexShortEdge)47 TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorDuplexShortEdge) {
48 constexpr char kTestPpdData[] =
49 R"(*PPD-Adobe: "4.3"
50 *OpenGroup: General/General
51 *OpenUI *ColorModel/Color Model: PickOne
52 *DefaultColorModel: Gray
53 *ColorModel Gray/Grayscale: "
54 <</cupsColorSpace 0/cupsColorOrder 0>>setpagedevice"
55 *ColorModel Black/Inverted Grayscale: "
56 <</cupsColorSpace 3/cupsColorOrder 0>>setpagedevice"
57 *CloseUI: *ColorModel
58 *OpenUI *Duplex/2-Sided Printing: PickOne
59 *DefaultDuplex: DuplexTumble
60 *Duplex None/Off: "
61 <</Duplex false>>setpagedevice"
62 *Duplex DuplexNoTumble/LongEdge: "
63 </Duplex true/Tumble false>>setpagedevice"
64 *Duplex DuplexTumble/ShortEdge: "
65 <</Duplex true/Tumble true>>setpagedevice"
66 *CloseUI: *Duplex
67 *CloseGroup: General)";
68
69 PrinterSemanticCapsAndDefaults caps;
70 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
71 kTestPpdData, &caps));
72 EXPECT_TRUE(caps.collate_capable);
73 EXPECT_TRUE(caps.collate_default);
74 EXPECT_EQ(caps.copies_max, 9999);
75 EXPECT_THAT(caps.duplex_modes,
76 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
77 mojom::DuplexMode::kLongEdge,
78 mojom::DuplexMode::kShortEdge));
79 EXPECT_EQ(mojom::DuplexMode::kShortEdge, caps.duplex_default);
80 EXPECT_FALSE(caps.color_changeable);
81 EXPECT_FALSE(caps.color_default);
82 }
83
84 // Test duplex detection code, which regressed in http://crbug.com/103999.
TEST(PrintBackendCupsHelperTest,TestPpdParsingNoColorDuplexSimples)85 TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorDuplexSimples) {
86 constexpr char kTestPpdData[] =
87 R"(*PPD-Adobe: "4.3"
88 *OpenGroup: General/General
89 *OpenUI *Duplex/Double-Sided Printing: PickOne
90 *DefaultDuplex: None
91 *Duplex None/Off: "
92 <</Duplex false>>setpagedevice"
93 *Duplex DuplexNoTumble/Long Edge (Standard): "
94 <</Duplex true/Tumble false>>setpagedevice"
95 *Duplex DuplexTumble/Short Edge (Flip): "
96 <</Duplex true/Tumble true>>setpagedevice"
97 *CloseUI: *Duplex
98 *CloseGroup: General)";
99
100 PrinterSemanticCapsAndDefaults caps;
101 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
102 kTestPpdData, &caps));
103 EXPECT_TRUE(caps.collate_capable);
104 EXPECT_TRUE(caps.collate_default);
105 EXPECT_EQ(caps.copies_max, 9999);
106 EXPECT_THAT(caps.duplex_modes,
107 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
108 mojom::DuplexMode::kLongEdge,
109 mojom::DuplexMode::kShortEdge));
110 EXPECT_EQ(mojom::DuplexMode::kSimplex, caps.duplex_default);
111 EXPECT_FALSE(caps.color_changeable);
112 EXPECT_FALSE(caps.color_default);
113 }
114
TEST(PrintBackendCupsHelperTest,TestPpdParsingNoColorNoDuplex)115 TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorNoDuplex) {
116 constexpr char kTestPpdData[] =
117 R"(*PPD-Adobe: "4.3"
118 *OpenGroup: General/General
119 *OpenUI *ColorModel/Color Model: PickOne
120 *DefaultColorModel: Gray
121 *ColorModel Gray/Grayscale: "
122 <</cupsColorSpace 0/cupsColorOrder 0>>setpagedevice"
123 *ColorModel Black/Inverted Grayscale: "
124 <</cupsColorSpace 3/cupsColorOrder 0>>setpagedevice"
125 *CloseUI: *ColorModel
126 *CloseGroup: General)";
127
128 PrinterSemanticCapsAndDefaults caps;
129 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
130 kTestPpdData, &caps));
131 EXPECT_TRUE(caps.collate_capable);
132 EXPECT_TRUE(caps.collate_default);
133 EXPECT_EQ(caps.copies_max, 9999);
134 EXPECT_THAT(caps.duplex_modes, testing::UnorderedElementsAre());
135 EXPECT_EQ(mojom::DuplexMode::kUnknownDuplexMode, caps.duplex_default);
136 EXPECT_FALSE(caps.color_changeable);
137 EXPECT_FALSE(caps.color_default);
138 }
139
TEST(PrintBackendCupsHelperTest,TestPpdParsingColorTrueDuplexShortEdge)140 TEST(PrintBackendCupsHelperTest, TestPpdParsingColorTrueDuplexShortEdge) {
141 constexpr char kTestPpdData[] =
142 R"(*PPD-Adobe: "4.3"
143 *ColorDevice: True
144 *DefaultColorSpace: CMYK
145 *OpenGroup: General/General
146 *OpenUI *ColorModel/Color Model: PickOne
147 *DefaultColorModel: CMYK
148 *ColorModel CMYK/Color: "(cmyk) RCsetdevicecolor"
149 *ColorModel Gray/Black and White: "(gray) RCsetdevicecolor"
150 *CloseUI: *ColorModel
151 *OpenUI *Duplex/2-Sided Printing: PickOne
152 *DefaultDuplex: DuplexTumble
153 *Duplex None/Off: "
154 <</Duplex false>>setpagedevice"
155 *Duplex DuplexNoTumble/LongEdge: "
156 <</Duplex true/Tumble false>>setpagedevice"
157 *Duplex DuplexTumble/ShortEdge: "
158 <</Duplex true/Tumble true>>setpagedevice"
159 *CloseUI: *Duplex
160 *CloseGroup: General)";
161
162 PrinterSemanticCapsAndDefaults caps;
163 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
164 kTestPpdData, &caps));
165 EXPECT_TRUE(caps.collate_capable);
166 EXPECT_TRUE(caps.collate_default);
167 EXPECT_EQ(caps.copies_max, 9999);
168 EXPECT_THAT(caps.duplex_modes,
169 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
170 mojom::DuplexMode::kLongEdge,
171 mojom::DuplexMode::kShortEdge));
172 EXPECT_EQ(mojom::DuplexMode::kShortEdge, caps.duplex_default);
173 EXPECT_TRUE(caps.color_changeable);
174 EXPECT_TRUE(caps.color_default);
175 }
176
TEST(PrintBackendCupsHelperTest,TestPpdParsingColorFalseDuplexLongEdge)177 TEST(PrintBackendCupsHelperTest, TestPpdParsingColorFalseDuplexLongEdge) {
178 constexpr char kTestPpdData[] =
179 R"(*PPD-Adobe: "4.3"
180 *ColorDevice: True
181 *DefaultColorSpace: CMYK
182 *OpenGroup: General/General
183 *OpenUI *ColorModel/Color Model: PickOne
184 *DefaultColorModel: Grayscale
185 *ColorModel Color/Color: "
186 %% FoomaticRIPOptionSetting: ColorModel=Color"
187 *FoomaticRIPOptionSetting ColorModel=Color: "
188 JCLDatamode=Color GSCmdLine=Color"
189 *ColorModel Grayscale/Grayscale: "
190 %% FoomaticRIPOptionSetting: ColorModel=Grayscale"
191 *FoomaticRIPOptionSetting ColorModel=Grayscale: "
192 JCLDatamode=Grayscale GSCmdLine=Grayscale"
193 *CloseUI: *ColorModel
194 *OpenUI *Duplex/2-Sided Printing: PickOne
195 *DefaultDuplex: DuplexNoTumble
196 *Duplex None/Off: "
197 <</Duplex false>>setpagedevice"
198 *Duplex DuplexNoTumble/LongEdge: "
199 <</Duplex true/Tumble false>>setpagedevice"
200 *Duplex DuplexTumble/ShortEdge: "
201 <</Duplex true/Tumble true>>setpagedevice"
202 *CloseUI: *Duplex
203 *CloseGroup: General)";
204
205 PrinterSemanticCapsAndDefaults caps;
206 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
207 kTestPpdData, &caps));
208 EXPECT_TRUE(caps.collate_capable);
209 EXPECT_TRUE(caps.collate_default);
210 EXPECT_EQ(caps.copies_max, 9999);
211 EXPECT_THAT(caps.duplex_modes,
212 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
213 mojom::DuplexMode::kLongEdge,
214 mojom::DuplexMode::kShortEdge));
215 EXPECT_EQ(mojom::DuplexMode::kLongEdge, caps.duplex_default);
216 EXPECT_TRUE(caps.color_changeable);
217 EXPECT_FALSE(caps.color_default);
218 }
219
TEST(PrintBackendCupsHelperTest,TestPpdParsingPageSize)220 TEST(PrintBackendCupsHelperTest, TestPpdParsingPageSize) {
221 constexpr char kTestPpdData[] =
222 R"(*PPD-Adobe: "4.3"
223 *OpenUI *PageSize: PickOne
224 *DefaultPageSize: Legal
225 *PageSize Letter/US Letter: "
226 <</DeferredMediaSelection true /PageSize [612 792]
227 /ImagingBBox null /MediaClass null >> setpagedevice"
228 *End
229 *PageSize Legal/US Legal: "
230 <</DeferredMediaSelection true /PageSize [612 1008]
231 /ImagingBBox null /MediaClass null >> setpagedevice"
232 *End
233 *DefaultPaperDimension: Legal
234 *PaperDimension Letter/US Letter: "612 792"
235 *PaperDimension Legal/US Legal: "612 1008"
236 *CloseUI: *PageSize)";
237
238 PrinterSemanticCapsAndDefaults caps;
239 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
240 kTestPpdData, &caps));
241 ASSERT_EQ(2UL, caps.papers.size());
242 EXPECT_EQ("Letter", caps.papers[0].vendor_id);
243 EXPECT_EQ("US Letter", caps.papers[0].display_name);
244 EXPECT_EQ(215900, caps.papers[0].size_um.width());
245 EXPECT_EQ(279400, caps.papers[0].size_um.height());
246 EXPECT_EQ("Legal", caps.papers[1].vendor_id);
247 EXPECT_EQ("US Legal", caps.papers[1].display_name);
248 EXPECT_EQ(215900, caps.papers[1].size_um.width());
249 EXPECT_EQ(355600, caps.papers[1].size_um.height());
250 EXPECT_TRUE(PapersEqual(caps.papers[1], caps.default_paper));
251 }
252
TEST(PrintBackendCupsHelperTest,TestPpdParsingPageSizeNoDefaultSpecified)253 TEST(PrintBackendCupsHelperTest, TestPpdParsingPageSizeNoDefaultSpecified) {
254 constexpr char kTestPpdData[] =
255 R"(*PPD-Adobe: "4.3"
256 *OpenUI *PageSize: PickOne
257 *PageSize A3/ISO A3: "
258 << /DeferredMediaSelection true /PageSize [842 1191]
259 /ImagingBBox null >> setpagedevice"
260 *End
261 *PageSize A4/ISO A4: "
262 << /DeferredMediaSelection true /PageSize [595 842]
263 /ImagingBBox null >> setpagedevice"
264 *End
265 *PageSize Legal/US Legal: "
266 << /DeferredMediaSelection true /PageSize [612 1008]
267 /ImagingBBox null >> setpagedevice"
268 *End
269 *PageSize Letter/US Letter: "
270 << /DeferredMediaSelection true /PageSize [612 792]
271 /ImagingBBox null >> setpagedevice"
272 *End
273 *PaperDimension A3/ISO A3: "842 1191"
274 *PaperDimension A4/ISO A4: "595 842"
275 *PaperDimension Legal/US Legal: "612 1008"
276 *PaperDimension Letter/US Letter: "612 792"
277 *CloseUI: *PageSize)";
278
279 {
280 PrinterSemanticCapsAndDefaults caps;
281 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"en-US",
282 kTestPpdData, &caps));
283 ASSERT_EQ(4UL, caps.papers.size());
284 EXPECT_EQ("Letter", caps.papers[3].vendor_id);
285 EXPECT_EQ("US Letter", caps.papers[3].display_name);
286 EXPECT_EQ(215900, caps.papers[3].size_um.width());
287 EXPECT_EQ(279400, caps.papers[3].size_um.height());
288 EXPECT_TRUE(PapersEqual(caps.papers[3], caps.default_paper));
289 }
290 {
291 PrinterSemanticCapsAndDefaults caps;
292 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"en-UK",
293 kTestPpdData, &caps));
294 ASSERT_EQ(4UL, caps.papers.size());
295 EXPECT_EQ("A4", caps.papers[1].vendor_id);
296 EXPECT_EQ("ISO A4", caps.papers[1].display_name);
297 EXPECT_EQ(209903, caps.papers[1].size_um.width());
298 EXPECT_EQ(297039, caps.papers[1].size_um.height());
299 EXPECT_TRUE(PapersEqual(caps.papers[1], caps.default_paper));
300 }
301 }
302
TEST(PrintBackendCupsHelperTest,TestPpdParsingBrotherPrinters)303 TEST(PrintBackendCupsHelperTest, TestPpdParsingBrotherPrinters) {
304 {
305 constexpr char kTestPpdData[] =
306 R"(*PPD-Adobe: "4.3"
307 *ColorDevice: True
308 *OpenUI *BRPrintQuality/Color/Mono: PickOne
309 *DefaultBRPrintQuality: Auto
310 *BRPrintQuality Auto/Auto: ""
311 *BRPrintQuality Color/Color: ""
312 *BRPrintQuality Black/Mono: ""
313 *CloseUI: *BRPrintQuality)";
314
315 PrinterSemanticCapsAndDefaults caps;
316 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
317 kTestPpdData, &caps));
318 EXPECT_TRUE(caps.color_changeable);
319 EXPECT_TRUE(caps.color_default);
320 EXPECT_EQ(mojom::ColorModel::kBrotherBRScript3Color, caps.color_model);
321 EXPECT_EQ(mojom::ColorModel::kBrotherBRScript3Black, caps.bw_model);
322 VerifyCapabilityColorModels(caps);
323 }
324 {
325 constexpr char kTestPpdData[] =
326 R"(*PPD-Adobe: "4.3"
327 *ColorDevice: True
328 *OpenUI *BRMonoColor/Color / Mono: PickOne
329 *DefaultBRMonoColor: Auto
330 *BRMonoColor Auto/Auto: ""
331 *BRMonoColor FullColor/Color: ""
332 *BRMonoColor Mono/Mono: ""
333 *CloseUI: *BRMonoColor)";
334
335 PrinterSemanticCapsAndDefaults caps;
336 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
337 kTestPpdData, &caps));
338 EXPECT_TRUE(caps.color_changeable);
339 EXPECT_TRUE(caps.color_default);
340 EXPECT_EQ(mojom::ColorModel::kBrotherCUPSColor, caps.color_model);
341 EXPECT_EQ(mojom::ColorModel::kBrotherCUPSMono, caps.bw_model);
342 VerifyCapabilityColorModels(caps);
343 }
344 {
345 constexpr char kTestPpdData[] =
346 R"(*PPD-Adobe: "4.3"
347 *ColorDevice: True
348 *OpenUI *BRDuplex/Two-Sided Printing: PickOne
349 *DefaultBRDuplex: DuplexTumble
350 *BRDuplex DuplexTumble/Short-Edge Binding: ""
351 *BRDuplex DuplexNoTumble/Long-Edge Binding: ""
352 *BRDuplex None/Off: ""
353 *CloseUI: *BRDuplex)";
354
355 PrinterSemanticCapsAndDefaults caps;
356 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
357 kTestPpdData, &caps));
358 EXPECT_THAT(caps.duplex_modes,
359 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
360 mojom::DuplexMode::kLongEdge,
361 mojom::DuplexMode::kShortEdge));
362 EXPECT_EQ(mojom::DuplexMode::kShortEdge, caps.duplex_default);
363 }
364 }
365
TEST(PrintBackendCupsHelperTest,TestPpdParsingHpPrinters)366 TEST(PrintBackendCupsHelperTest, TestPpdParsingHpPrinters) {
367 constexpr char kTestPpdData[] =
368 R"(*PPD-Adobe: "4.3"
369 *ColorDevice: True
370 *OpenUI *HPColorMode/Mode: PickOne
371 *DefaultHPColorMode: ColorPrint
372 *HPColorMode ColorPrint/Color: "
373 << /ProcessColorModel /DeviceCMYK >> setpagedevice"
374 *HPColorMode GrayscalePrint/Grayscale: "
375 << /ProcessColorModel /DeviceGray >> setpagedevice"
376 *CloseUI: *HPColorMode)";
377
378 PrinterSemanticCapsAndDefaults caps;
379 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
380 kTestPpdData, &caps));
381 EXPECT_TRUE(caps.color_changeable);
382 EXPECT_TRUE(caps.color_default);
383 EXPECT_EQ(mojom::ColorModel::kHPColorColor, caps.color_model);
384 EXPECT_EQ(mojom::ColorModel::kHPColorBlack, caps.bw_model);
385 VerifyCapabilityColorModels(caps);
386 }
387
TEST(PrintBackendCupsHelperTest,TestPpdParsingEpsonPrinters)388 TEST(PrintBackendCupsHelperTest, TestPpdParsingEpsonPrinters) {
389 constexpr char kTestPpdData[] =
390 R"(*PPD-Adobe: "4.3"
391 *ColorDevice: True
392 *OpenUI *Ink/Ink: PickOne
393 *DefaultInk: COLOR
394 *Ink COLOR/Color: "
395 <</cupsBitsPerColor 8 /cupsColorOrder 0
396 /cupsColorSpace 1 /cupsCompression 1>> setpagedevice"
397 *Ink MONO/Monochrome: "
398 <</cupsBitsPerColor 8 /cupsColorOrder 0
399 /cupsColorSpace 0 /cupsCompression 1>> setpagedevice"
400 *CloseUI: *Ink)";
401
402 PrinterSemanticCapsAndDefaults caps;
403 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
404 kTestPpdData, &caps));
405 EXPECT_TRUE(caps.color_changeable);
406 EXPECT_TRUE(caps.color_default);
407 EXPECT_EQ(mojom::ColorModel::kEpsonInkColor, caps.color_model);
408 EXPECT_EQ(mojom::ColorModel::kEpsonInkMono, caps.bw_model);
409 VerifyCapabilityColorModels(caps);
410 }
411
TEST(PrintBackendCupsHelperTest,TestPpdParsingSamsungPrinters)412 TEST(PrintBackendCupsHelperTest, TestPpdParsingSamsungPrinters) {
413 constexpr char kTestPpdData[] =
414 R"(*PPD-Adobe: "4.3"
415 *ColorDevice: True
416 *OpenUI *ColorMode/Color Mode: Boolean
417 *DefaultColorMode: True
418 *ColorMode False/Grayscale: ""
419 *ColorMode True/Color: ""
420 *CloseUI: *ColorMode)";
421
422 PrinterSemanticCapsAndDefaults caps;
423 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
424 kTestPpdData, &caps));
425 EXPECT_TRUE(caps.color_changeable);
426 EXPECT_TRUE(caps.color_default);
427 EXPECT_EQ(mojom::ColorModel::kColorModeColor, caps.color_model);
428 EXPECT_EQ(mojom::ColorModel::kColorModeMonochrome, caps.bw_model);
429 VerifyCapabilityColorModels(caps);
430 }
431
TEST(PrintBackendCupsHelperTest,TestPpdParsingSharpPrinters)432 TEST(PrintBackendCupsHelperTest, TestPpdParsingSharpPrinters) {
433 constexpr char kTestPpdData[] =
434 R"(*PPD-Adobe: "4.3"
435 *ColorDevice: True
436 *OpenUI *ARCMode/Color Mode: PickOne
437 *OrderDependency: 180 AnySetup *ARCMode
438 *DefaultARCMode: CMAuto
439 *ARCMode CMAuto/Automatic: ""
440 *End
441 *ARCMode CMColor/Color: ""
442 *End
443 *ARCMode CMBW/Black and White: ""
444 *End
445 *CloseUI: *ARCMode)";
446
447 PrinterSemanticCapsAndDefaults caps;
448 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
449 kTestPpdData, &caps));
450 EXPECT_TRUE(caps.color_changeable);
451 EXPECT_TRUE(caps.color_default);
452 EXPECT_EQ(mojom::ColorModel::kSharpARCModeCMColor, caps.color_model);
453 EXPECT_EQ(mojom::ColorModel::kSharpARCModeCMBW, caps.bw_model);
454 VerifyCapabilityColorModels(caps);
455 }
456
TEST(PrintBackendCupsHelperTest,TestPpdParsingXeroxPrinters)457 TEST(PrintBackendCupsHelperTest, TestPpdParsingXeroxPrinters) {
458 constexpr char kTestPpdData[] =
459 R"(*PPD-Adobe: "4.3"
460 *ColorDevice: True
461 *OpenUI *XRXColor/Color Correction: PickOne
462 *OrderDependency: 48.0 AnySetup *XRXColor
463 *DefaultXRXColor: Automatic
464 *XRXColor Automatic/Automatic: "
465 <</ProcessColorModel /DeviceCMYK>> setpagedevice"
466 *XRXColor BW/Black and White: "
467 <</ProcessColorModel /DeviceGray>> setpagedevice"
468 *CloseUI: *XRXColor)";
469
470 PrinterSemanticCapsAndDefaults caps;
471 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
472 kTestPpdData, &caps));
473 EXPECT_TRUE(caps.color_changeable);
474 EXPECT_TRUE(caps.color_default);
475 EXPECT_EQ(mojom::ColorModel::kXeroxXRXColorAutomatic, caps.color_model);
476 EXPECT_EQ(mojom::ColorModel::kXeroxXRXColorBW, caps.bw_model);
477 VerifyCapabilityColorModels(caps);
478 }
479
TEST(PrintBackendCupsHelperTest,TestPpdParsingCupsMaxCopies)480 TEST(PrintBackendCupsHelperTest, TestPpdParsingCupsMaxCopies) {
481 {
482 constexpr char kTestPpdData[] =
483 R"(*PPD-Adobe: "4.3"
484 *cupsMaxCopies: 99
485 *OpenUI *ColorMode/Color Mode: Boolean
486 *DefaultColorMode: True
487 *CloseUI: *ColorMode)";
488
489 PrinterSemanticCapsAndDefaults caps;
490 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
491 kTestPpdData, &caps));
492 EXPECT_EQ(99, caps.copies_max);
493 }
494
495 {
496 constexpr char kTestPpdData[] =
497 R"(*PPD-Adobe: "4.3"
498 *cupsMaxCopies: notavalidnumber
499 *OpenUI *ColorMode/Color Mode: Boolean
500 *DefaultColorMode: True
501 *CloseUI: *ColorMode)";
502
503 PrinterSemanticCapsAndDefaults caps;
504 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
505 kTestPpdData, &caps));
506 EXPECT_EQ(9999, caps.copies_max);
507 }
508 }
509
TEST(PrintBackendCupsHelperTest,TestPpdParsingResolutionTagNames)510 TEST(PrintBackendCupsHelperTest, TestPpdParsingResolutionTagNames) {
511 constexpr const char* kTestResNames[] = {"Resolution", "JCLResolution",
512 "SetResolution", "CNRes_PGP",
513 "HPPrintQuality", "LXResolution"};
514 const std::vector<gfx::Size> kExpectedResolutions = {gfx::Size(600, 600)};
515 PrinterSemanticCapsAndDefaults caps;
516 for (const char* res_name : kTestResNames) {
517 EXPECT_TRUE(ParsePpdCapabilities(
518 /*dest=*/nullptr, /*locale=*/"",
519 GeneratePpdResolutionTestData(res_name).c_str(), &caps));
520 EXPECT_EQ(kExpectedResolutions, caps.dpis);
521 EXPECT_EQ(kExpectedResolutions[0], caps.default_dpi);
522 }
523 }
524
TEST(PrintBackendCupsHelperTest,TestPpdParsingResolutionInvalidDefaultResolution)525 TEST(PrintBackendCupsHelperTest,
526 TestPpdParsingResolutionInvalidDefaultResolution) {
527 constexpr char kTestPpdData[] =
528 R"(*PPD-Adobe: "4.3"
529 *OpenUI *Resolution/Resolution: PickOne
530 *DefaultResolution: 500dpi
531 *Resolution 600dpi/600 dpi: ""
532 *CloseUI: *Resolution)";
533
534 PrinterSemanticCapsAndDefaults caps;
535 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
536 kTestPpdData, &caps));
537 EXPECT_EQ(std::vector<gfx::Size>{gfx::Size(600, 600)}, caps.dpis);
538 EXPECT_TRUE(caps.default_dpi.IsEmpty());
539 }
540
TEST(PrintBackendCupsHelperTest,TestPpdParsingResolutionNoResolution)541 TEST(PrintBackendCupsHelperTest, TestPpdParsingResolutionNoResolution) {
542 constexpr char kTestPpdData[] =
543 R"(*PPD-Adobe: "4.3"
544 *OpenUI *Resolution/Resolution: PickOne
545 *CloseUI: *Resolution)";
546
547 PrinterSemanticCapsAndDefaults caps;
548 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
549 kTestPpdData, &caps));
550 EXPECT_TRUE(caps.dpis.empty());
551 EXPECT_TRUE(caps.default_dpi.IsEmpty());
552 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
553 "*PPD-Adobe: \"4.3\"", &caps));
554 EXPECT_TRUE(caps.dpis.empty());
555 EXPECT_TRUE(caps.default_dpi.IsEmpty());
556 }
557
TEST(PrintBackendCupsHelperTest,TestPpdParsingResolutionNoDefaultResolution)558 TEST(PrintBackendCupsHelperTest, TestPpdParsingResolutionNoDefaultResolution) {
559 constexpr char kTestPpdData[] =
560 R"(*PPD-Adobe: "4.3"
561 *OpenUI *Resolution/Resolution: PickOne
562 *Resolution 600dpi/600 dpi: ""
563 *CloseUI: *Resolution)";
564
565 PrinterSemanticCapsAndDefaults caps;
566 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
567 kTestPpdData, &caps));
568 EXPECT_EQ(std::vector<gfx::Size>{gfx::Size(600, 600)}, caps.dpis);
569 EXPECT_TRUE(caps.default_dpi.IsEmpty());
570 }
571
TEST(PrintBackendCupsHelperTest,TestPpdParsingResolutionDpiFormat)572 TEST(PrintBackendCupsHelperTest, TestPpdParsingResolutionDpiFormat) {
573 constexpr char kTestPpdData[] =
574 R"(*PPD-Adobe: "4.3"
575 *JCLOpenUI *Resolution/Resolution: PickOne
576 *OrderDependency: 100 JCLSetup *Resolution
577 *DefaultResolution: 600dpi
578 *Resolution 500x500dpi/500 dpi: " "
579 *Resolution 0.5dpi/0.5 dpi: " "
580 *Resolution 5.0dpi/5 dpi: " "
581 *Resolution 600dpi/600 dpi: " "
582 *Resolution 0dpi/0 dpi: " "
583 *Resolution 1e1dpi/10 dpi: " "
584 *Resolution -3dpi/-3 dpi: " "
585 *Resolution -3x300dpi/dpi: " "
586 *Resolution 300x0dpi/dpi: " "
587 *Resolution 50/50: " "
588 *Resolution 50dpis/50 dpis: " "
589 *Resolution 30x30dpis/30 dpis: " "
590 *Resolution 2400x600dpi/HQ1200: " "
591 *JCLCloseUI: *Resolution)";
592
593 const std::vector<gfx::Size> kExpectedResolutions = {
594 gfx::Size(500, 500), gfx::Size(600, 600), gfx::Size(2400, 600)};
595 PrinterSemanticCapsAndDefaults caps;
596 EXPECT_TRUE(ParsePpdCapabilities(/*dest=*/nullptr, /*locale=*/"",
597 kTestPpdData, &caps));
598 EXPECT_EQ(kExpectedResolutions, caps.dpis);
599 EXPECT_EQ(kExpectedResolutions[1], caps.default_dpi);
600 }
601
TEST(PrintBackendCupsHelperTest,TestPpdSetsDestOptions)602 TEST(PrintBackendCupsHelperTest, TestPpdSetsDestOptions) {
603 constexpr char kTestPpdData[] =
604 R"(*PPD-Adobe: "4.3"
605 *OpenUI *Duplex/2-Sided Printing: PickOne
606 *DefaultDuplex: DuplexTumble
607 *Duplex None/Off: "
608 <</Duplex false>>setpagedevice"
609 *Duplex DuplexNoTumble/LongEdge: "
610 </Duplex true/Tumble false>>setpagedevice"
611 *Duplex DuplexTumble/ShortEdge: "
612 <</Duplex true/Tumble true>>setpagedevice"
613 *CloseUI: *Duplex)";
614
615 cups_dest_t* dest;
616 int num_dests = 0;
617 num_dests =
618 cupsAddDest(/*name=*/"test_dest", /*instance=*/nullptr, num_dests, &dest);
619 ASSERT_EQ(1, num_dests);
620
621 // Set long edge duplex mode in the destination options even though the PPD
622 // sets short edge duplex mode as the default.
623 cups_option_t* options = nullptr;
624 int num_options = 0;
625 num_options =
626 cupsAddOption("Duplex", "DuplexNoTumble", num_options, &options);
627 dest->num_options = num_options;
628 dest->options = options;
629
630 PrinterSemanticCapsAndDefaults caps;
631 EXPECT_TRUE(ParsePpdCapabilities(dest, /*locale=*/"", kTestPpdData, &caps));
632 EXPECT_THAT(caps.duplex_modes,
633 testing::UnorderedElementsAre(mojom::DuplexMode::kSimplex,
634 mojom::DuplexMode::kLongEdge,
635 mojom::DuplexMode::kShortEdge));
636 EXPECT_EQ(mojom::DuplexMode::kLongEdge, caps.duplex_default);
637
638 cupsFreeDests(num_dests, dest);
639 }
640
641 } // namespace printing
642