1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/printing/ppd_line_reader.h"
#include <memory>
#include <string>
#include <vector>
#include "base/strings/string_split.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace {
// Test ppd contents. This is an excerpt from an HPLIP ppd.
const char* kTestPpd = R"PPD(*PPD-Adobe: "4.3"
*%%%% PPD file for HP PSC 900 Series with CUPS.
*%%%% Created by the CUPS PPD Compiler CUPS v1.5.0.
*% (c) 2008 Copyright HP Development Company, LP
*FormatVersion: "4.3"
*FileVersion: "3.17.9"
*LanguageVersion: English
*LanguageEncoding: ISOLatin1
*PCFileName: "hp-psc_900_series.ppd"
*Product: "(HP PSC 900 All-in-one Printer)"
*Manufacturer: "HP"
*ModelName: "HP PSC 900 Series"
*ShortNickName: "HP PSC 900 Series"
*NickName: "HP PSC 900 Series, hpcups 3.17.9"
*PSVersion: "(3010.000) 0"
*LanguageLevel: "3"
*ColorDevice: True
*DefaultColorSpace: RGB
*FileSystem: False
*Throughput: "1"
*LandscapeOrientation: Plus90
*TTRasterizer: Type42
*% Driver-defined attributes...
*RequiresPageRegion All: True
*cupsEvenDuplex: True
*cupsBackSide: "Rotated"
*cupsFlipDuplex: True
*hpPrinterLanguage: "pcl3gui"
*hpPrinterPlatform: "dj970"
*HPMechOffset: "70"
*cupsModelName: "DESKJET 930"
*1284DeviceID: "MFG:HP;MDL:psc 900 series;DES:psc 900 series;"
*cupsVersion: 1.5
)PPD";
// This is the exact same contents as kTestPpd, but gzipped
// with gzip --best.
const uint8_t kTestPpdGzipped[] = {
0x1f, 0x8b, 0x08, 0x08, 0xd9, 0x8c, 0xef, 0x59, 0x02, 0x03, 0x70, 0x70,
0x64, 0x67, 0x7a, 0x69, 0x70, 0x70, 0x65, 0x64, 0x2e, 0x70, 0x70, 0x64,
0x00, 0x7d, 0x93, 0x51, 0x6f, 0xda, 0x30, 0x10, 0xc7, 0xdf, 0xf9, 0x14,
0x16, 0xd2, 0x24, 0x40, 0x25, 0x0a, 0xd0, 0xa9, 0x85, 0x3e, 0xb5, 0x09,
0x94, 0xae, 0x50, 0x2c, 0xc2, 0xf6, 0x5a, 0x99, 0xe4, 0x92, 0x78, 0x35,
0xb6, 0xe7, 0xd8, 0x6c, 0xec, 0xd3, 0xef, 0x9c, 0x50, 0x60, 0x9b, 0xd4,
0x3c, 0xfe, 0xff, 0x77, 0xe7, 0xbb, 0xdf, 0x5d, 0x7a, 0x94, 0xc6, 0xfd,
0xfb, 0x4c, 0x6d, 0x61, 0x42, 0xda, 0xd7, 0xc1, 0xa8, 0xdd, 0xea, 0x7d,
0xc2, 0x8f, 0xa0, 0x4c, 0x72, 0x2e, 0x80, 0xe4, 0xca, 0x90, 0x39, 0x25,
0x34, 0x89, 0xc8, 0x38, 0x0c, 0x49, 0x02, 0x86, 0x43, 0x45, 0x7e, 0x72,
0x5b, 0x92, 0xe8, 0x2b, 0x4d, 0x82, 0x63, 0x7c, 0x64, 0x80, 0x59, 0xc8,
0xc8, 0xf6, 0x40, 0x6c, 0x09, 0xb5, 0x55, 0xd7, 0x88, 0xd4, 0x4e, 0x63,
0x19, 0xd3, 0x28, 0xfb, 0x41, 0xf0, 0x39, 0x08, 0x7d, 0x0e, 0xe9, 0xa4,
0x5d, 0x32, 0x0c, 0xc3, 0x5b, 0x8c, 0xd0, 0x07, 0xc3, 0x8b, 0xd2, 0xfa,
0x67, 0x62, 0xd8, 0x83, 0x50, 0x7a, 0x07, 0xd2, 0xd6, 0xa9, 0x4c, 0x1e,
0xae, 0xc8, 0x82, 0xb6, 0x7a, 0x33, 0x65, 0x76, 0xcc, 0x7e, 0x03, 0x53,
0x71, 0x25, 0x4f, 0xad, 0xce, 0xb0, 0xf4, 0x59, 0x1b, 0x05, 0x83, 0x9b,
0x60, 0x8c, 0xf2, 0x82, 0xc9, 0xc2, 0xb1, 0xe2, 0x6c, 0x4d, 0x65, 0x21,
0x78, 0x55, 0x9e, 0x9d, 0xa9, 0x4c, 0x55, 0xc6, 0x65, 0x31, 0x21, 0x4f,
0xc9, 0x6a, 0xc1, 0x2c, 0x97, 0x83, 0x56, 0x8f, 0x46, 0xbe, 0xde, 0x0b,
0xdb, 0x79, 0x16, 0xa5, 0xee, 0xeb, 0x2a, 0x7d, 0xc5, 0x99, 0x5f, 0xab,
0x7a, 0xe6, 0x40, 0xeb, 0x0c, 0x6b, 0x53, 0xa3, 0x32, 0x97, 0x5a, 0x8c,
0xe8, 0x5c, 0x60, 0xb9, 0x17, 0xa2, 0xcf, 0x65, 0x5f, 0x49, 0x20, 0xd4,
0x70, 0x69, 0xc1, 0x74, 0x31, 0x76, 0xc9, 0xa4, 0xcb, 0x59, 0x6a, 0x9d,
0x01, 0x83, 0x09, 0x73, 0xea, 0x35, 0x95, 0x81, 0x38, 0xbe, 0xf1, 0x1f,
0x57, 0xf4, 0x93, 0x52, 0x19, 0xfb, 0xc2, 0xd3, 0xb7, 0x0f, 0x62, 0x3e,
0xb2, 0xaf, 0x48, 0xa9, 0x53, 0xa7, 0x2b, 0x72, 0xa2, 0x41, 0x93, 0x33,
0xa2, 0xce, 0x28, 0x1c, 0x84, 0x41, 0x18, 0x86, 0x5d, 0x12, 0x5e, 0x80,
0x5a, 0x78, 0xec, 0x9e, 0x20, 0x6a, 0x91, 0x12, 0xca, 0xe0, 0x1e, 0x78,
0x8a, 0xf5, 0x37, 0xc6, 0x41, 0xab, 0x17, 0x43, 0xce, 0x9c, 0xb0, 0xb5,
0x93, 0x68, 0xe6, 0x8d, 0xf5, 0xe3, 0x43, 0x83, 0x3f, 0x39, 0x54, 0x16,
0x76, 0x13, 0x32, 0x63, 0xa2, 0xc2, 0xd0, 0x4d, 0x69, 0x94, 0x2b, 0x4a,
0xed, 0x3c, 0xa1, 0x41, 0xf3, 0x44, 0x56, 0xa5, 0x4c, 0xc3, 0x0a, 0xbb,
0x93, 0x16, 0x51, 0xfb, 0x46, 0xa8, 0x70, 0xd5, 0x38, 0xc4, 0xf0, 0xcd,
0x9a, 0x61, 0xbe, 0xe1, 0xbf, 0x3d, 0xa1, 0xcd, 0x41, 0xc3, 0xf5, 0xd0,
0x5f, 0x47, 0x6c, 0xf8, 0x1e, 0x4c, 0x3f, 0x83, 0x9c, 0x4b, 0xbc, 0x2a,
0x66, 0xad, 0xe1, 0x5b, 0x67, 0x71, 0x0b, 0x01, 0x5e, 0xcf, 0x1a, 0x7e,
0x38, 0x6e, 0xa0, 0xa2, 0xd8, 0xfa, 0x1a, 0x0a, 0xac, 0xe8, 0x17, 0xf0,
0xde, 0xad, 0x9f, 0x7e, 0xba, 0x07, 0x19, 0x3b, 0x2d, 0xe0, 0xd7, 0xa5,
0xfa, 0xc0, 0xd2, 0xb7, 0x84, 0x67, 0x9e, 0xdb, 0x5a, 0x59, 0x7f, 0xaf,
0xed, 0xc6, 0x98, 0x09, 0xae, 0xff, 0x0e, 0x2f, 0xf5, 0x71, 0x8f, 0xef,
0x88, 0x30, 0x47, 0xa7, 0x62, 0x54, 0x38, 0xde, 0xbe, 0x70, 0xa9, 0x60,
0x16, 0xff, 0x10, 0x9c, 0xbf, 0x9d, 0x7d, 0x1f, 0xdf, 0x78, 0xa6, 0x73,
0xba, 0x84, 0xb4, 0x5c, 0xe5, 0x79, 0x05, 0x9e, 0x41, 0xad, 0xf9, 0x37,
0x2e, 0x17, 0x1f, 0x4f, 0x93, 0xe7, 0x2f, 0xd3, 0x0d, 0x19, 0x8f, 0xbc,
0x3b, 0x18, 0xde, 0x5e, 0x37, 0xc0, 0x9f, 0x62, 0x34, 0x97, 0xb3, 0xc7,
0xc9, 0x9c, 0xde, 0x2d, 0xe3, 0xc5, 0x04, 0x2f, 0xb0, 0x5e, 0x6d, 0x73,
0x81, 0x77, 0x98, 0xf6, 0xaf, 0x74, 0x2c, 0x7e, 0xda, 0x30, 0xfe, 0x60,
0xad, 0x3f, 0xe6, 0x78, 0x79, 0x4f, 0xd4, 0x03, 0x00, 0x00};
constexpr int kPpdMaxLineLength = 255;
// Read |ppd_contents| line by line with a reader using |max_line_length| as the
// line limit. Expect the read lines to be the same as |expected_lines|.
void RunTest(const std::string& ppd_contents,
int max_line_length,
const std::vector<std::string>& expected_lines) {
auto reader = PpdLineReader::Create(ppd_contents, max_line_length);
std::string actual;
for (const std::string& expected : expected_lines) {
ASSERT_TRUE(reader->NextLine(&actual));
EXPECT_EQ(expected, actual);
}
EXPECT_FALSE(reader->NextLine(&actual));
}
// Trivial empty ppd test.
TEST(PpdLineReaderTest, Empty) {
RunTest("", kPpdMaxLineLength, {});
}
// Read kTestPpd contents.
TEST(PpdLineReaderTest, SimplePpd) {
std::vector<std::string> expected = base::SplitString(
kTestPpd, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
RunTest(kTestPpd, kPpdMaxLineLength, expected);
}
// Same as SimplePpd test, but with gzipped contents.
TEST(PpdLineReaderTest, SimplePpdGzipped) {
std::vector<std::string> expected = base::SplitString(
kTestPpd, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
RunTest(std::string(reinterpret_cast<const char*>(kTestPpdGzipped),
sizeof(kTestPpdGzipped)),
kPpdMaxLineLength, expected);
}
// Test that we skip lines exceeding max_line_length.
TEST(PpdLineReaderTest, SkipLongLines) {
// 35 characters is about the median line length in our sample data.
constexpr int kMaxLineLength = 35;
std::vector<std::string> expected = base::SplitString(
kTestPpd, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::erase_if(expected, [](const std::string& entry) -> bool {
return entry.size() > kMaxLineLength;
});
RunTest(kTestPpd, kMaxLineLength, expected);
}
// Same as above, but on gzipped data.
TEST(PpdLineReaderTest, SkipLongLinesGzipped) {
constexpr int kMaxLineLength = 35;
std::vector<std::string> expected = base::SplitString(
kTestPpd, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::erase_if(expected, [](const std::string& entry) -> bool {
return entry.size() > kMaxLineLength;
});
RunTest(std::string(reinterpret_cast<const char*>(kTestPpdGzipped),
sizeof(kTestPpdGzipped)),
kMaxLineLength, expected);
}
// Test that we get a reasonable error if we try to process corrupt gzip data.
TEST(PpdLineReaderTest, CorruptGzipData) {
std::string gzipped_contents(reinterpret_cast<const char*>(kTestPpdGzipped),
sizeof(kTestPpdGzipped));
// Corrupt the contents by zeroing out most of it after the header.
for (unsigned int i = 50; i < sizeof(kTestPpdGzipped); ++i) {
gzipped_contents[i] = 0;
}
auto reader = PpdLineReader::Create(gzipped_contents, kPpdMaxLineLength);
// Read as far as we can before the gzip stream gives up.
std::string unused;
while (reader->NextLine(&unused)) {
// Nop.
}
// Should have flagged an error because the gzip data was corrupt.
EXPECT_TRUE(reader->Error());
// The same test for RemainingContent().
reader = PpdLineReader::Create(gzipped_contents, kPpdMaxLineLength);
reader->RemainingContent();
EXPECT_TRUE(reader->Error());
}
// Tests that the simple PPD begins with the magic number which is present at
// the beginning of all PPD files.
TEST(PpdLineReaderTest, SimplePpdContainsMagicNumber) {
EXPECT_TRUE(PpdLineReader::ContainsMagicNumber(kTestPpd, kPpdMaxLineLength));
}
// Tests that the Gzipped version of the PPD file begins with the magic number.
TEST(PpdLineReaderTest, GzippedPpdContainsMagicNumber) {
const std::string gzipped_contents(
reinterpret_cast<const char*>(kTestPpdGzipped), sizeof(kTestPpdGzipped));
EXPECT_TRUE(
PpdLineReader::ContainsMagicNumber(gzipped_contents, kPpdMaxLineLength));
}
// Tests that a file which does not begin with the PPD magic number will be
// rejected.
TEST(PpdLineReaderTest, InvalidPpdMagicNumber) {
EXPECT_FALSE(PpdLineReader::ContainsMagicNumber(
"*%%%% PPD file for HP PSC 900 Series with CUPS.", kPpdMaxLineLength));
EXPECT_FALSE(PpdLineReader::ContainsMagicNumber("MZ this is fake exe file",
kPpdMaxLineLength));
EXPECT_FALSE(PpdLineReader::ContainsMagicNumber("PK this is a fake zip file",
kPpdMaxLineLength));
}
// Tests that a file which begins with newline characters should still be
// rejected even if it contains the magic number since it does not appear at the
// beginning of the file.
TEST(PpdLineReaderTest, RejectFileStartingWithNewline) {
EXPECT_FALSE(PpdLineReader::ContainsMagicNumber("\x0A*PPD-Adobe: \"4.3\"",
kPpdMaxLineLength));
EXPECT_FALSE(PpdLineReader::ContainsMagicNumber("\x0D*PPD-Adobe: \"4.3\"",
kPpdMaxLineLength));
}
TEST(PpdLineReaderTest, RemainingContentForGzippedData) {
const std::string gzipped(reinterpret_cast<const char*>(kTestPpdGzipped),
sizeof(kTestPpdGzipped));
const std::string ungzipped(kTestPpd);
// `max_line_length` should not matter for RemainingContent().
auto reader = PpdLineReader::Create(gzipped, /*max_line_length=*/30);
EXPECT_EQ(reader->RemainingContent(), ungzipped);
EXPECT_FALSE(reader->Error());
// We are at the end. There is nothing more to read.
std::string unused;
EXPECT_FALSE(reader->NextLine(&unused));
}
TEST(PpdLineReaderTest, RemainingContentForUncompressedData) {
const std::string ungzipped(kTestPpd);
// `max_line_length` should not matter for RemainingContent().
auto reader = PpdLineReader::Create(ungzipped, /*max_line_length=*/30);
EXPECT_EQ(reader->RemainingContent(), ungzipped);
EXPECT_FALSE(reader->Error());
// We are at the end. There is nothing more to read.
std::string unused;
EXPECT_FALSE(reader->NextLine(&unused));
}
} // namespace
} // namespace chromeos
|