Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
lzw_decompressor_unittest.cpp
Go to the documentation of this file.
1// Copyright 2017 The PDFium Authors
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 "core/fxcodec/gif/lzw_decompressor.h"
6
7#include <stdint.h>
8#include <string.h>
9
10#include <iterator>
11
12#include "core/fxcrt/data_vector.h"
13#include "testing/gmock/include/gmock/gmock.h"
14#include "testing/gtest/include/gtest/gtest.h"
15
16using ::testing::ElementsAreArray;
17
18TEST(LZWDecompressor, CreateBadParams) {
19 EXPECT_FALSE(LZWDecompressor::Create(0x10, 0x02));
20 EXPECT_FALSE(LZWDecompressor::Create(0x04, 0x0F));
21 EXPECT_FALSE(LZWDecompressor::Create(0x02, 0x02));
22}
23
24TEST(LZWDecompressor, ExtractData) {
25 uint8_t palette_exp = 0x1;
26 uint8_t code_exp = 0x2;
27 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
28 ASSERT_NE(nullptr, decompressor);
29
30 // Check that 0 length extract does nothing
31 {
32 DataVector<uint8_t>* decompressed = decompressor->DecompressedForTest();
33 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
34 *(decompressor->DecompressedNextForTest()) = decompressed->size();
35 uint8_t dest_buf[20];
36 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
37
38 EXPECT_EQ(0u, decompressor->ExtractDataForTest(dest_buf, 0));
39 for (size_t i = 0; i < std::size(dest_buf); ++i)
40 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
41
42 EXPECT_EQ(10u, *(decompressor->DecompressedNextForTest()));
43 for (size_t i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
44 EXPECT_EQ(i, (*decompressed)[i]);
45 }
46
47 // Check that less than decompressed size only gets the expected number
48 {
49 DataVector<uint8_t>* decompressed = decompressor->DecompressedForTest();
50 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
51 *(decompressor->DecompressedNextForTest()) = decompressed->size();
52 uint8_t dest_buf[20];
53 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
54
55 EXPECT_EQ(5u, decompressor->ExtractDataForTest(dest_buf, 5));
56 size_t i = 0;
57 for (; i < 5; ++i)
58 EXPECT_EQ(9 - i, dest_buf[i]);
59 for (; i < std::size(dest_buf); ++i)
60 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
61
62 EXPECT_EQ(5u, *(decompressor->DecompressedNextForTest()));
63 for (i = 0; i < *(decompressor->DecompressedNextForTest()); ++i)
64 EXPECT_EQ(i, (*decompressed)[i]);
65 }
66
67 // Check that greater than decompressed size depletes the decompressor
68 {
69 DataVector<uint8_t>* decompressed = decompressor->DecompressedForTest();
70 *decompressed = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
71 *(decompressor->DecompressedNextForTest()) = decompressed->size();
72 uint8_t dest_buf[20];
73 memset(dest_buf, static_cast<uint8_t>(-1), sizeof(dest_buf));
74
75 EXPECT_EQ(10u,
76 decompressor->ExtractDataForTest(dest_buf, std::size(dest_buf)));
77 size_t i = 0;
78 for (; i < 10; ++i)
79 EXPECT_EQ(9 - i, dest_buf[i]);
80 for (; i < std::size(dest_buf); ++i)
81 EXPECT_EQ(static_cast<uint8_t>(-1), dest_buf[i]);
82
83 EXPECT_EQ(0u, *(decompressor->DecompressedNextForTest()));
84 }
85}
86
87TEST(LZWDecompressor, DecodeBadParams) {
88 uint8_t palette_exp = 0x0;
89 uint8_t code_exp = 0x2;
90 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
91 ASSERT_NE(nullptr, decompressor);
92
93 uint8_t image_data[10];
94 uint32_t image_size = std::size(image_data);
95
96 uint8_t output_data[10];
97 uint32_t output_size = std::size(output_data);
98
99 decompressor->SetSource(nullptr, image_size);
100 EXPECT_EQ(LZWDecompressor::Status::kError,
101 decompressor->Decode(output_data, &output_size));
102
103 decompressor->SetSource(image_data, 0);
104 EXPECT_EQ(LZWDecompressor::Status::kUnfinished,
105 decompressor->Decode(output_data, &output_size));
106
107 decompressor->SetSource(image_data, image_size);
108 EXPECT_EQ(LZWDecompressor::Status::kError,
109 decompressor->Decode(nullptr, &output_size));
110 EXPECT_EQ(LZWDecompressor::Status::kError,
111 decompressor->Decode(output_data, nullptr));
112
113 output_size = 0;
114 EXPECT_EQ(LZWDecompressor::Status::kInsufficientDestSize,
115 decompressor->Decode(output_data, &output_size));
116}
117
118TEST(LZWDecompressor, Decode1x1SingleColour) {
119 uint8_t palette_exp = 0x0;
120 uint8_t code_exp = 0x2;
121 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
122 ASSERT_NE(nullptr, decompressor);
123
124 uint8_t image_data[] = {0x44, 0x01};
125 uint32_t image_size = std::size(image_data);
126
127 uint8_t expected_data[] = {0x00};
128 uint8_t output_data[std::size(expected_data)];
129 memset(output_data, 0, sizeof(output_data));
130 uint32_t output_size = std::size(output_data);
131
132 decompressor->SetSource(image_data, image_size);
133 EXPECT_EQ(LZWDecompressor::Status::kSuccess,
134 decompressor->Decode(output_data, &output_size));
135
136 EXPECT_EQ(std::size(output_data), output_size);
137 EXPECT_TRUE(0 == memcmp(expected_data, output_data, sizeof(expected_data)));
138}
139
140TEST(LZWDecompressor, Decode10x10SingleColour) {
141 uint8_t palette_exp = 0x0;
142 uint8_t code_exp = 0x2;
143 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
144 ASSERT_NE(nullptr, decompressor);
145
146 static constexpr uint8_t kImageData[] = {0x84, 0x8F, 0xA9, 0xCB,
147 0xED, 0x0F, 0x63, 0x2B};
148 uint32_t image_size = std::size(kImageData);
149
150 static constexpr uint8_t kExpectedData[] = {
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00};
160 uint8_t output_data[std::size(kExpectedData)];
161 memset(output_data, 0, sizeof(output_data));
162 uint32_t output_size = std::size(output_data);
163
164 decompressor->SetSource(kImageData, image_size);
165 EXPECT_EQ(LZWDecompressor::Status::kSuccess,
166 decompressor->Decode(output_data, &output_size));
167
168 EXPECT_EQ(std::size(output_data), output_size);
169 EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
170}
171
173 uint8_t palette_exp = 0x1;
174 uint8_t code_exp = 0x2;
175 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
176 ASSERT_NE(nullptr, decompressor);
177
178 static constexpr uint8_t kImageData[] = {
179 0x8C, 0x2D, 0x99, 0x87, 0x2A, 0x1C, 0xDC, 0x33, 0xA0, 0x02, 0x75,
180 0xEC, 0x95, 0xFA, 0xA8, 0xDE, 0x60, 0x8C, 0x04, 0x91, 0x4C, 0x01};
181 uint32_t image_size = std::size(kImageData);
182
183 static constexpr uint8_t kExpectedData[] = {
184 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
185 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
186 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
187 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02,
188 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
189 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
190 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
191 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
192 0x01, 0x01, 0x01, 0x01};
193
194 uint8_t output_data[std::size(kExpectedData)];
195 memset(output_data, 0, sizeof(output_data));
196 uint32_t output_size = std::size(output_data);
197
198 decompressor->SetSource(kImageData, image_size);
199 EXPECT_EQ(LZWDecompressor::Status::kSuccess,
200 decompressor->Decode(output_data, &output_size));
201
202 EXPECT_EQ(std::size(output_data), output_size);
203 EXPECT_TRUE(0 == memcmp(kExpectedData, output_data, sizeof(kExpectedData)));
204}
205
206TEST(LZWDecompressor, MultipleDecodes) {
207 auto decompressor = LZWDecompressor::Create(/*color_exp=*/0, /*code_exp=*/2);
208 ASSERT_NE(nullptr, decompressor);
209
210 static constexpr uint8_t kImageData[] = {0x84, 0x6f, 0x05};
211 decompressor->SetSource(kImageData, std::size(kImageData));
212
213 static constexpr uint8_t kExpectedScanline[] = {0x00, 0x00, 0x00, 0x00};
214 uint8_t output_data[std::size(kExpectedScanline)];
215
216 memset(output_data, 0xFF, sizeof(output_data));
217 uint32_t output_size = std::size(output_data);
218 EXPECT_EQ(LZWDecompressor::Status::kInsufficientDestSize,
219 decompressor->Decode(output_data, &output_size));
220 EXPECT_EQ(std::size(kExpectedScanline), output_size);
221 EXPECT_THAT(output_data, ElementsAreArray(kExpectedScanline));
222
223 memset(output_data, 0xFF, sizeof(output_data));
224 output_size = std::size(output_data);
225 EXPECT_EQ(LZWDecompressor::Status::kSuccess,
226 decompressor->Decode(output_data, &output_size));
227 EXPECT_EQ(std::size(kExpectedScanline), output_size);
228 EXPECT_THAT(output_data, ElementsAreArray(kExpectedScanline));
229}
230
232 uint8_t palette_exp = 0x2; // Image uses 10 colours, so the palette exp
233 // should be 3, 2^(3+1) = 16 colours.
234 uint8_t code_exp = 0x4;
235 auto decompressor = LZWDecompressor::Create(palette_exp, code_exp);
236 ASSERT_NE(nullptr, decompressor);
237
238 static constexpr uint8_t kImageData[] = {
239 0x30, 0xC9, 0x49, 0x81, 0xBD, 0x78, 0xE8, 0xCD, 0x89, 0xFF,
240 0x60, 0x20, 0x8E, 0xE4, 0x61, 0x9E, 0xA8, 0xA1, 0xAE, 0x2C,
241 0xE2, 0xBE, 0xB0, 0x20, 0xCF, 0x74, 0x61, 0xDF, 0x78, 0x04};
242 uint32_t image_size = std::size(kImageData);
243
244 uint8_t output_data[100]; // The uncompressed data is for a 10x10 image
245 memset(output_data, 0, sizeof(output_data));
246 uint32_t output_size = std::size(output_data);
247
248 decompressor->SetSource(kImageData, image_size);
249 EXPECT_EQ(LZWDecompressor::Status::kError,
250 decompressor->Decode(output_data, &output_size));
251}
TEST(LZWDecompressor, CreateBadParams)