1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <fcntl.h>
17 #include <gtest/gtest.h>
18 #include <memory>
19
20 #include "file_metadata_stream.h"
21 #include "image_source.h"
22 #include "media_errors.h"
23 #include "metadata_accessor.h"
24
25 using namespace OHOS::Media;
26 using namespace testing::ext;
27
28 namespace OHOS {
29 namespace Multimedia {
30 namespace {
31 static const std::string IMAGE_GET_FILTER_AREA_HEIF_PATH = "/data/local/tmp/image/get_filter_area.heic";
32 static const std::string IMAGE_GET_FILTER_AREA_JPEG_PATH = "/data/local/tmp/image/get_filter_area.jpg";
33 static const std::string IMAGE_GET_FILTER_AREA_PNG_PATH = "/data/local/tmp/image/get_filter_area.png";
34 static const std::string IMAGE_GET_FILTER_AREA_WEBP_PATH = "/data/local/tmp/image/get_filter_area.webp";
35 static const std::string IMAGE_GET_FILTER_AREA_DNG_PATH = "/data/local/tmp/image/get_filter_area.dng";
36 static const std::string IMAGE_GET_FILTER_AREA_DNG_FILTERED_PATH = "/data/local/tmp/image/get_filter_area_filtered.dng";
37 static const std::string IMAGE_NO_GPS_HEIF_PATH = "/data/local/tmp/image/test.heic";
38 static const std::string IMAGE_NO_GPS_JPEG_PATH = "/data/local/tmp/image/test_jpeg_readexifblob003.jpg";
39 static const std::string IMAGE_NO_GPS_PNG_PATH = "/data/local/tmp/image/test_exif.png";
40 static const std::string IMAGE_NO_GPS_WEBP_PATH = "/data/local/tmp/image/test_webp_readmetadata008.webp";
41 static const std::string IMAGE_INPUT_ITXT_WITHCOMPRESS_PNG_PATH =
42 "/data/local/tmp/image/test_chunk_itxt_withcompress.png";
43 static const uint8_t GPSAltitude[] = {0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
44 static const uint8_t GPSSatellites[] = {0x35, 0x20, 0x38, 0x20, 0x32, 0x30};
45 static const uint8_t GPSStatus[] = {0x56};
46 static const uint8_t GPSMeasureMode[] = {0x32};
47 static const uint8_t GPSDOP[] = {0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
48 static const uint8_t GPSSpeed[] = {0x46, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
49 static const uint8_t GPSTrackRef[] = {0x54};
50 static const uint8_t GPSTrack[] = {0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
51 static const uint8_t GPSImgDirection[] = {0x4a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00};
52 static const int MAX_FILE_SIZE = 1000 * 1000 * 100;
53 static const std::vector<std::string> gpsExifKeys{
54 "GPSAltitude",
55 "GPSSatellites",
56 "GPSStatus",
57 "GPSMeasureMode",
58 "GPSDOP",
59 "GPSSpeed",
60 "GPSTrackRef",
61 "GPSTrack",
62 "GPSImgDirection"
63 };
64 static const std::vector<std::string> dngExifKeys{
65 "GPSVersionID",
66 "GPSLatitudeRef",
67 "GPSLatitude",
68 "GPSLongitudeRef",
69 "GPSLongitude",
70 "GPSAltitude",
71 "GPSSatellites",
72 "GPSStatus",
73 "GPSMeasureMode",
74 "GPSDOP",
75 "GPSSpeed",
76 "GPSTrackRef",
77 "GPSTrack",
78 "GPSImgDirection",
79 "GPSDateStamp",
80 "GPSHPositioningError",
81 "Make",
82 "Model",
83 "DateTimeOriginal",
84 "LensMake",
85 };
86 }
87
88 class ExifGetFilterAreaTest : public testing::Test {
89 public:
ExifGetFilterAreaTest()90 ExifGetFilterAreaTest() {}
~ExifGetFilterAreaTest()91 ~ExifGetFilterAreaTest() {}
92
93 void CopyFileStream(std::fstream &src, std::fstream &dst);
94 };
95
CopyFileStream(std::fstream & src,std::fstream & dst)96 void ExifGetFilterAreaTest::CopyFileStream(std::fstream &src, std::fstream &dst)
97 {
98 src.seekg(0, src.end);
99 long size = src.tellg();
100 src.seekg(0);
101 if (size > MAX_FILE_SIZE) {
102 return;
103 }
104 char* buffer = new char[size];
105 src.read(buffer, size);
106 dst.write(buffer, size);
107 delete[] buffer;
108 dst.seekg(0);
109 }
110
111 /**
112 * @tc.name: GetFilterArea001
113 * @tc.desc: test GetFilterArea(filterType, ranges)
114 * @tc.type: FUNC
115 */
116 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea001, TestSize.Level3)
117 {
118 std::unique_ptr<std::fstream> fs = std::make_unique<std::fstream>();
119 fs->open(IMAGE_GET_FILTER_AREA_HEIF_PATH, std::fstream::binary | std::fstream::in);
120 bool isOpen = fs->is_open();
121 ASSERT_EQ(isOpen, true);
122 uint32_t errorCode = 0;
123 SourceOptions opts;
124 std::fstream& fileStream = *fs;
125 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(std::move(fs), opts, errorCode);
126 ASSERT_NE(imageSource, nullptr);
127 std::vector<std::pair<uint32_t, uint32_t>> ranges;
128 std::vector<std::vector<char>> contents;
129 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
130 ASSERT_EQ(ret, SUCCESS);
131 for (const auto& range : ranges) {
132 fileStream.seekg(range.first, std::ios::beg);
133 std::vector<char> content(range.second);
134 fileStream.read(reinterpret_cast<char *>(content.data()), range.second);
135 contents.push_back(content);
136 }
137 int i = 0;
138 ASSERT_EQ(std::memcmp(GPSAltitude, contents[i].data(), contents[i].size()), SUCCESS);
139 i++;
140 ASSERT_EQ(std::memcmp(GPSSatellites, contents[i].data(), contents[i].size()), SUCCESS);
141 i++;
142 ASSERT_EQ(std::memcmp(GPSStatus, contents[i].data(), contents[i].size()), SUCCESS);
143 i++;
144 ASSERT_EQ(std::memcmp(GPSMeasureMode, contents[i].data(), contents[i].size()), SUCCESS);
145 i++;
146 ASSERT_EQ(std::memcmp(GPSDOP, contents[i].data(), contents[i].size()), SUCCESS);
147 i++;
148 ASSERT_EQ(std::memcmp(GPSSpeed, contents[i].data(), contents[i].size()), SUCCESS);
149 i++;
150 ASSERT_EQ(std::memcmp(GPSTrackRef, contents[i].data(), contents[i].size()), SUCCESS);
151 i++;
152 ASSERT_EQ(std::memcmp(GPSTrack, contents[i].data(), contents[i].size()), SUCCESS);
153 i++;
154 ASSERT_EQ(std::memcmp(GPSImgDirection, contents[i].data(), contents[i].size()), SUCCESS);
155 }
156
157 /**
158 * @tc.name: GetFilterArea002
159 * @tc.desc: test GetFilterArea(filterType, ranges)
160 * @tc.type: FUNC
161 */
162 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea002, TestSize.Level3)
163 {
164 std::unique_ptr<std::fstream> fs = std::make_unique<std::fstream>();
165 fs->open(IMAGE_GET_FILTER_AREA_PNG_PATH, std::fstream::binary | std::fstream::in);
166 bool isOpen = fs->is_open();
167 ASSERT_EQ(isOpen, true);
168 uint32_t errorCode = 0;
169 SourceOptions opts;
170 std::fstream& fileStream = *fs;
171 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(std::move(fs), opts, errorCode);
172 ASSERT_NE(imageSource, nullptr);
173 std::vector<std::pair<uint32_t, uint32_t>> ranges;
174 std::vector<std::vector<char>> contents;
175 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
176 ASSERT_EQ(ret, SUCCESS);
177 for (const auto& range : ranges) {
178 fileStream.seekg(range.first, std::ios::beg);
179 std::vector<char> content(range.second);
180 fileStream.read(reinterpret_cast<char *>(content.data()), range.second);
181 contents.push_back(content);
182 }
183 int i = 0;
184 ASSERT_EQ(std::memcmp(GPSAltitude, contents[i].data(), contents[i].size()), SUCCESS);
185 i++;
186 ASSERT_EQ(std::memcmp(GPSSatellites, contents[i].data(), contents[i].size()), SUCCESS);
187 i++;
188 ASSERT_EQ(std::memcmp(GPSStatus, contents[i].data(), contents[i].size()), SUCCESS);
189 i++;
190 ASSERT_EQ(std::memcmp(GPSMeasureMode, contents[i].data(), contents[i].size()), SUCCESS);
191 i++;
192 ASSERT_EQ(std::memcmp(GPSDOP, contents[i].data(), contents[i].size()), SUCCESS);
193 i++;
194 ASSERT_EQ(std::memcmp(GPSSpeed, contents[i].data(), contents[i].size()), SUCCESS);
195 i++;
196 ASSERT_EQ(std::memcmp(GPSTrackRef, contents[i].data(), contents[i].size()), SUCCESS);
197 i++;
198 ASSERT_EQ(std::memcmp(GPSTrack, contents[i].data(), contents[i].size()), SUCCESS);
199 i++;
200 ASSERT_EQ(std::memcmp(GPSImgDirection, contents[i].data(), contents[i].size()), SUCCESS);
201 }
202
203 /**
204 * @tc.name: GetFilterArea003
205 * @tc.desc: test GetFilterArea(filterType, ranges)
206 * @tc.type: FUNC
207 */
208 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea003, TestSize.Level3)
209 {
210 std::unique_ptr<std::fstream> fs = std::make_unique<std::fstream>();
211 fs->open(IMAGE_GET_FILTER_AREA_JPEG_PATH, std::fstream::binary | std::fstream::in);
212 bool isOpen = fs->is_open();
213 ASSERT_EQ(isOpen, true);
214 uint32_t errorCode = 0;
215 SourceOptions opts;
216 std::fstream& fileStream = *fs;
217 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(std::move(fs), opts, errorCode);
218 ASSERT_NE(imageSource, nullptr);
219 std::vector<std::pair<uint32_t, uint32_t>> ranges;
220 std::vector<std::vector<char>> contents;
221 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
222 ASSERT_EQ(ret, SUCCESS);
223 for (const auto& range : ranges) {
224 fileStream.seekg(range.first, std::ios::beg);
225 std::vector<char> content(range.second);
226 fileStream.read(reinterpret_cast<char *>(content.data()), range.second);
227 contents.push_back(content);
228 }
229 int i = 0;
230 ASSERT_EQ(std::memcmp(GPSAltitude, contents[i].data(), contents[i].size()), SUCCESS);
231 i++;
232 ASSERT_EQ(std::memcmp(GPSSatellites, contents[i].data(), contents[i].size()), SUCCESS);
233 i++;
234 ASSERT_EQ(std::memcmp(GPSStatus, contents[i].data(), contents[i].size()), SUCCESS);
235 i++;
236 ASSERT_EQ(std::memcmp(GPSMeasureMode, contents[i].data(), contents[i].size()), SUCCESS);
237 i++;
238 ASSERT_EQ(std::memcmp(GPSDOP, contents[i].data(), contents[i].size()), SUCCESS);
239 i++;
240 ASSERT_EQ(std::memcmp(GPSSpeed, contents[i].data(), contents[i].size()), SUCCESS);
241 i++;
242 ASSERT_EQ(std::memcmp(GPSTrackRef, contents[i].data(), contents[i].size()), SUCCESS);
243 i++;
244 ASSERT_EQ(std::memcmp(GPSTrack, contents[i].data(), contents[i].size()), SUCCESS);
245 i++;
246 ASSERT_EQ(std::memcmp(GPSImgDirection, contents[i].data(), contents[i].size()), SUCCESS);
247 }
248
249 /**
250 * @tc.name: GetFilterArea004
251 * @tc.desc: test GetFilterArea(filterType, ranges)
252 * @tc.type: FUNC
253 */
254 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea004, TestSize.Level3)
255 {
256 std::unique_ptr<std::fstream> fs = std::make_unique<std::fstream>();
257 fs->open(IMAGE_GET_FILTER_AREA_WEBP_PATH, std::fstream::binary | std::fstream::in);
258 bool isOpen = fs->is_open();
259 ASSERT_EQ(isOpen, true);
260 uint32_t errorCode = 0;
261 SourceOptions opts;
262 std::fstream& fileStream = *fs;
263 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(std::move(fs), opts, errorCode);
264 ASSERT_NE(imageSource, nullptr);
265 std::vector<std::pair<uint32_t, uint32_t>> ranges;
266 std::vector<std::vector<char>> contents;
267 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
268 ASSERT_EQ(ret, SUCCESS);
269 for (const auto& range : ranges) {
270 fileStream.seekg(range.first, std::ios::beg);
271 std::vector<char> content(range.second);
272 fileStream.read(reinterpret_cast<char *>(content.data()), range.second);
273 contents.push_back(content);
274 }
275 int i = 0;
276 ASSERT_EQ(std::memcmp(GPSAltitude, contents[i].data(), contents[i].size()), SUCCESS);
277 i++;
278 ASSERT_EQ(std::memcmp(GPSSatellites, contents[i].data(), contents[i].size()), SUCCESS);
279 i++;
280 ASSERT_EQ(std::memcmp(GPSStatus, contents[i].data(), contents[i].size()), SUCCESS);
281 i++;
282 ASSERT_EQ(std::memcmp(GPSMeasureMode, contents[i].data(), contents[i].size()), SUCCESS);
283 i++;
284 ASSERT_EQ(std::memcmp(GPSDOP, contents[i].data(), contents[i].size()), SUCCESS);
285 i++;
286 ASSERT_EQ(std::memcmp(GPSSpeed, contents[i].data(), contents[i].size()), SUCCESS);
287 i++;
288 ASSERT_EQ(std::memcmp(GPSTrackRef, contents[i].data(), contents[i].size()), SUCCESS);
289 i++;
290 ASSERT_EQ(std::memcmp(GPSTrack, contents[i].data(), contents[i].size()), SUCCESS);
291 i++;
292 ASSERT_EQ(std::memcmp(GPSImgDirection, contents[i].data(), contents[i].size()), SUCCESS);
293 }
294
295 /**
296 * @tc.name: GetFilterArea
297 * @tc.desc: test GetFilterArea005
298 * @tc.type: FUNC
299 */
300 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea005, TestSize.Level3)
301 {
302 uint32_t errorCode = 0;
303 SourceOptions opts;
304 std::unique_ptr<ImageSource> imageSource =
305 ImageSource::CreateImageSource(IMAGE_GET_FILTER_AREA_WEBP_PATH, opts, errorCode);
306 ASSERT_NE(imageSource, nullptr);
307 std::vector<std::pair<uint32_t, uint32_t>> ranges;
308 std::vector<std::string> keys;
309 uint32_t ret = imageSource->GetFilterArea(keys, ranges);
310 ASSERT_EQ(ret, ERR_IMAGE_INVALID_PARAMETER);
311 }
312
313 /**
314 * @tc.name: GetFilterArea
315 * @tc.desc: test GetFilterArea006
316 * @tc.type: FUNC
317 */
318 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea006, TestSize.Level3)
319 {
320 uint32_t errorCode = 0;
321 SourceOptions opts;
322 std::unique_ptr<ImageSource> imageSource =
323 ImageSource::CreateImageSource(IMAGE_INPUT_ITXT_WITHCOMPRESS_PNG_PATH, opts, errorCode);
324 ASSERT_NE(imageSource, nullptr);
325 std::vector<std::pair<uint32_t, uint32_t>> ranges;
326 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
327 ASSERT_EQ(ret, E_NO_EXIF_TAG);
328 }
329
330 /**
331 * @tc.name: GetFilterArea
332 * @tc.desc: test GetFilterArea007
333 * @tc.type: FUNC
334 */
335 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea007, TestSize.Level3)
336 {
337 uint32_t errorCode = 0;
338 SourceOptions opts;
339 std::unique_ptr<ImageSource> imageSource =
340 ImageSource::CreateImageSource(IMAGE_NO_GPS_HEIF_PATH, opts, errorCode);
341 ASSERT_NE(imageSource, nullptr);
342 std::vector<std::pair<uint32_t, uint32_t>> ranges;
343 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
344 ASSERT_EQ(ret, E_NO_EXIF_TAG);
345 }
346
347 /**
348 * @tc.name: GetFilterArea
349 * @tc.desc: test GetFilterArea008
350 * @tc.type: FUNC
351 */
352 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea008, TestSize.Level3)
353 {
354 uint32_t errorCode = 0;
355 SourceOptions opts;
356 std::unique_ptr<ImageSource> imageSource =
357 ImageSource::CreateImageSource(IMAGE_NO_GPS_JPEG_PATH, opts, errorCode);
358 ASSERT_NE(imageSource, nullptr);
359 std::vector<std::pair<uint32_t, uint32_t>> ranges;
360 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
361 ASSERT_EQ(ret, E_NO_EXIF_TAG);
362 }
363
364 /**
365 * @tc.name: GetFilterArea
366 * @tc.desc: test GetFilterArea009
367 * @tc.type: FUNC
368 */
369 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea009, TestSize.Level3)
370 {
371 uint32_t errorCode = 0;
372 SourceOptions opts;
373 std::unique_ptr<ImageSource> imageSource =
374 ImageSource::CreateImageSource(IMAGE_NO_GPS_PNG_PATH, opts, errorCode);
375 ASSERT_NE(imageSource, nullptr);
376 std::vector<std::pair<uint32_t, uint32_t>> ranges;
377 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
378 ASSERT_EQ(ret, E_NO_EXIF_TAG);
379 }
380
381 /**
382 * @tc.name: GetFilterArea
383 * @tc.desc: test GetFilterArea010
384 * @tc.type: FUNC
385 */
386 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea010, TestSize.Level3)
387 {
388 uint32_t errorCode = 0;
389 SourceOptions opts;
390 std::unique_ptr<ImageSource> imageSource =
391 ImageSource::CreateImageSource(IMAGE_NO_GPS_WEBP_PATH, opts, errorCode);
392 ASSERT_NE(imageSource, nullptr);
393 std::vector<std::pair<uint32_t, uint32_t>> ranges;
394 uint32_t ret = imageSource->GetFilterArea(gpsExifKeys, ranges);
395 ASSERT_EQ(ret, E_NO_EXIF_TAG);
396 }
397
398 /**
399 * @tc.name: GetFilterArea011
400 * @tc.desc: test GetFilterArea dng
401 * @tc.type: FUNC
402 */
403 HWTEST_F(ExifGetFilterAreaTest, GetFilterArea011, TestSize.Level3)
404 {
405 std::unique_ptr<std::fstream> fs = std::make_unique<std::fstream>();
406 std::unique_ptr<std::fstream> fsOut = std::make_unique<std::fstream>();
407 fs->open(IMAGE_GET_FILTER_AREA_DNG_PATH, std::fstream::binary | std::fstream::in);
408 fsOut->open(IMAGE_GET_FILTER_AREA_DNG_FILTERED_PATH,
409 std::fstream::binary | std::fstream::out);
410 bool isOpen = fs->is_open();
411 bool isOutOpen = fsOut->is_open();
412 ASSERT_EQ(isOpen && isOutOpen, true);
413 uint32_t errorCode = 0;
414 SourceOptions opts;
415 std::fstream& fileStream = *fs;
416 std::fstream& fileOutStream = *fsOut;
417 CopyFileStream(fileStream, fileOutStream);
418 std::unique_ptr<ImageSource> imageSource = ImageSource::CreateImageSource(
419 IMAGE_GET_FILTER_AREA_DNG_PATH, opts, errorCode);
420 ASSERT_NE(imageSource, nullptr);
421 std::vector<std::string> values;
422 for (int i = 0; i < dngExifKeys.size(); ++i) {
423 std::string tmp = "";
424 errorCode = imageSource->GetImagePropertyString(0, dngExifKeys[i], tmp);
425 ASSERT_EQ(errorCode, SUCCESS);
426 values.emplace_back(tmp);
427 }
428 std::vector<std::pair<uint32_t, uint32_t>> ranges;
429 uint32_t ret = imageSource->GetFilterArea(dngExifKeys, ranges);
430 ASSERT_EQ(ret, SUCCESS);
431 for (const auto& range : ranges) {
432 fileOutStream.seekg(range.first, std::ios::beg);
433 std::vector<char> buf(range.second, 0);
434 fileOutStream.write(reinterpret_cast<char *>(buf.data()), range.second);
435 }
436 fileOutStream.seekg(0);
437 fileOutStream.close();
438 fileStream.close();
439 std::unique_ptr<ImageSource> imageSource2 = ImageSource::CreateImageSource(
440 IMAGE_GET_FILTER_AREA_DNG_FILTERED_PATH, opts, errorCode);
441 ASSERT_NE(imageSource2, nullptr);
442 std::vector<std::string> filteredValues;
443 for (int i = 0; i < dngExifKeys.size(); ++i) {
444 std::string tmp = "";
445 errorCode = imageSource2->GetImagePropertyString(0, dngExifKeys[i], tmp);
446 ASSERT_EQ(errorCode, SUCCESS);
447 filteredValues.emplace_back(tmp);
448 }
449 ASSERT_EQ(values.size(), filteredValues.size());
450 for (int i = 0; i < dngExifKeys.size(); ++i) {
451 ASSERT_NE(values[i], filteredValues[i]);
452 }
453 }
454 } // namespace Multimedia
455 } // namespace OHOS